tl;博士; 当您看到“Is A”关系时,请使用继承/抽象类。当你看到“有”关系时,创建成员变量。当您看到“依赖于外部提供者”时,实现(而不是继承)一个接口。
面试题:接口和抽象类有什么区别?你如何决定何时使用什么?我大多得到以下一个或全部答案: 答案 1:您不能创建抽象类和接口的对象。
ZK(那是我的姓名缩写):你不能创建任何一个对象。所以这没有区别。这是接口和抽象类之间的相似之处。反问:为什么不能创建抽象类或接口的对象?
答案 2:抽象类可以有一个函数体作为部分/默认实现。
ZK:反问:所以如果我把它改成一个纯抽象类,把所有的虚函数都标记为抽象,并且不为任何虚函数提供默认实现。那会使抽象类和接口相同吗?之后它们可以互换使用吗?
答案 3:接口允许多重继承,而抽象类不允许。
ZK:反问:你真的继承自一个接口吗?还是您只是实现一个接口并从抽象类继承?实现和继承有什么区别?这些反题让候选人望而却步,让大多数人摸不着头脑,或者直接跳到下一个问题。这让我觉得人们在面向对象编程的这些基本构建块方面需要帮助。原始问题和所有反问题的答案都可以在英语和 UML 中找到。您必须至少了解以下内容才能更好地理解这两个结构。
普通名词:普通名词是给同一类或同类事物“共同”的名称。例如水果、动物、城市、汽车等。
专有名词:专有名词是物体、地点或事物的名称。苹果、猫、纽约、本田雅阁等。
汽车是普通名词。而本田雅阁是一个专有名词,可能是一个复合专有名词,一个由两个名词组成的专有名词。
来到 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 支持充气轮胎和加油”。