我迟到了 10 年,但我想尝试任何方式。几天前写了一篇关于相同的帖子。想把它贴在这里。
tl;博士;当您看到“Is A”关系时,请使用继承/抽象类。当你看到“有”关系时,创建成员变量。当您看到“依赖于外部提供者”时,实现(而不是继承)一个接口。
面试题:接口和抽象类有什么区别?你如何决定何时使用什么?
我大多得到以下一个或全部答案:
答案1:不能创建抽象类和接口的对象。
ZK(这是我的首字母缩写):你不能创建任何一个对象。所以这没有区别。这是接口和抽象类之间的相似之处。柜台
问题:为什么不能创建抽象类或接口的对象?
答案 2: 抽象类可以有一个函数体作为部分/默认实现。
ZK: 反问:所以如果我把它改成一个纯抽象类,把所有的虚函数都标记为抽象并且不为任何虚函数提供默认实现。那会使抽象类和接口相同吗?之后它们可以互换使用吗?
答案 3:接口允许多重继承,而抽象类不允许。
ZK: 反问:你真的从接口继承吗?还是您只是实现一个接口并从抽象类继承?实现和继承有什么区别?
这些反题让候选人望而却步,让大多数人摸不着头脑,或者直接跳到下一个问题。这让我觉得人们在面向对象编程的这些基本构建块方面需要帮助。
原始问题和所有反问题的答案都可以在英语和 UML 中找到。
您必须至少了解以下内容才能更好地理解这两个构造。
普通名词:普通名词是对同一类或同类事物“共同”给予的名称。例如水果、动物、城市、汽车等。
专有名词:专有名词是物体、地点或事物的名称。 Apple、Cat、New York、Honda Accord 等
汽车是普通名词。而本田雅阁是一个专有名词,也可能是一个复合专有名词,一个由两个名词组成的专有名词。
来到 UML 部分。您应该熟悉以下关系:
让我们考虑以下两个句子。
- 本田雅阁是汽车吗?
- 本田雅阁有车吗?
哪一个听起来是正确的?简单的英语和理解力。 HondaAccord 和 Cars 共享“Is A”关系。本田雅阁没有汽车。这是辆车。本田雅阁“有一个”音乐播放器。
当两个实体共享“Is A”关系时,它更适合继承。并且有一个关系是创建成员变量的更好候选者。
有了这个,我们的代码看起来像这样:
abstract class Car
{
string color;
int speed;
}
class HondaAccord : Car
{
MusicPlayer musicPlayer;
}
现在本田不生产音乐播放器。或者至少这不是他们的主要业务。
于是他们联系了其他公司并签订了合同。如果您在此处接收电源并在这两根电线上接收输出信号,它将在这些扬声器上正常播放。
这使得音乐播放器成为界面的完美候选者。只要连接工作正常,您不在乎谁为其提供支持。
您可以用索尼或其他方式替换 LG 的 MusicPlayer。它不会改变本田雅阁的任何事情。
为什么不能创建抽象类的对象?
因为你不能走进陈列室说给我一辆车。你必须提供一个专有名词。什么车?可能是本田雅阁。那时销售代理可以为您提供一些东西。
为什么不能创建接口的对象?
因为你不能走进陈列室说给我一份音乐播放器的合同。它没有帮助。接口位于消费者和提供者之间,只是为了促进达成协议。您将如何处理该协议的副本?它不会播放音乐。
为什么接口允许多重继承?
接口不被继承。实现了接口。
接口是与外部世界交互的候选者。
本田雅阁有一个加油接口。它有给轮胎充气的接口。还有用来给足球充气的软管。所以新代码如下所示:
abstract class Car
{
string color;
int speed;
}
class HondaAccord : Car, IInflateAir, IRefueling
{
MusicPlayer musicPlayer;
}
而英文会这样写:“Honda Accord is a Car 支持充气轮胎和加油”。