接口和抽象类之间到底有什么区别?
当前回答
我迟到10年了,但我想尝试任何方法。几天前写了一篇同样的帖子。我想把它张贴在这里。
tl;博士当您看到“Is A”关系时,请使用继承/抽象类。当您看到“有”关系时,创建成员变量。当您看到“依赖于外部提供程序”时,实现(而不是继承)一个接口。
面试问题:接口和抽象类有什么区别?你如何决定何时使用什么?我通常会得到以下一个或全部答案:答案1:不能创建抽象类和接口的对象。
ZK(这是我的首字母缩写):你不能创建任何一个对象。所以这并不是什么区别。这是接口和抽象类之间的相似之处。柜台问题:为什么不能创建抽象类或接口的对象?
答案2:抽象类可以有一个函数体作为部分/默认实现。
ZK:反问题:所以如果我将其更改为纯抽象类,将所有虚拟函数标记为抽象,并且不为任何虚拟函数提供默认实现。这会使抽象类和接口相同吗?之后它们可以互换使用吗?
答案3:接口允许多重继承,抽象类不允许。
ZK:反问:你真的从接口继承吗?还是只实现一个接口,从抽象类继承?实现和继承之间有什么区别?这些反问题会让考生们措手不及,让大多数人挠头,或者直接进入下一个问题。这让我觉得人们需要帮助来构建面向对象编程的基本构件。原始问题和所有反问题的答案都可以在英语和UML中找到。为了更好地理解这两个结构,您必须至少了解以下内容。
共同名词:共同名词是指同一类或同一种类的事物的“共同”名称。例如水果、动物、城市、汽车等。
专有名词:专有名词是物体、地点或事物的名称。苹果、猫、纽约、本田雅阁等。
汽车是一个通用名词。本田雅阁是一个专有名词,可能是一个合成专有名词,一个由两个名词组成的专有名词。
来到UML部分。您应该熟悉以下关系:
是A有A使用
让我们考虑下面的两句话。-本田雅阁是一辆车?-本田雅阁有车吗?
哪一个听起来正确?简单的英语和理解能力。本田雅阁(HondaAccord)和汽车(Cars)有着“是A”的关系。本田雅阁(Honda accord)没有车,它“是”一辆车。本田雅阁“有一个”音乐播放器。
当两个实体共享“Is A”关系时,它更适合继承。Has a relationship是创建成员变量的更好候选。这样,我们的代码如下所示:
abstract class Car
{
string color;
int speed;
}
class HondaAccord : Car
{
MusicPlayer musicPlayer;
}
现在本田不生产音乐播放器。或者至少这不是他们的主要业务。
因此,他们联系其他公司并签订合同。如果你在这里接收到电源和这两条电线上的输出信号,它在这些扬声器上会播放得很好。
这使得Music Player成为界面的完美候选。你不在乎谁为它提供支持,只要连接正常即可。
您可以用索尼或其他方式替换LG的MusicPlayer。这不会改变本田雅阁的任何事情。
为什么不能创建抽象类的对象?
因为你不能走进展厅说给我一辆车。你必须提供一个专有名词。什么车?可能是本田雅阁。这就是销售代理可以给你东西的时候。
为什么不能创建接口的对象?因为你不能走进展厅说给我一份音乐播放器的合同。这没用。接口位于消费者和提供者之间,只是为了促成协议。你将如何处理协议副本?它不会播放音乐。
为什么接口允许多重继承?
接口未被继承。接口已实现。界面是与外部世界交互的候选界面。本田雅阁有一个加油接口。它有给轮胎充气的接口。和用来给足球充气的软管一样。因此,新代码如下所示:
abstract class Car
{
string color;
int speed;
}
class HondaAccord : Car, IInflateAir, IRefueling
{
MusicPlayer musicPlayer;
}
英文的意思是“本田雅阁是一款支持轮胎充气和加油的汽车”。
其他回答
抽象类与接口的主题主要是语义。
抽象类在不同的编程语言中通常充当接口的超集,除了一点,即可以实现多个接口,但只能继承一个类。
接口定义了某件事情必须能够做的事情;类似于合同,但不提供其实现。
抽象类定义了什么是什么,它通常托管子类之间的共享代码。
例如,格式化程序应该能够格式化()某些内容。描述这种情况的常见语义是创建一个接口IFormatter,该接口带有一个format()声明,其作用类似于一个契约。但是IFormatter并不描述什么是什么,而是描述它应该能够做什么。在本例中,我们创建一个抽象类。。。因此,我们创建了一个实现接口的抽象类Formatter。这是一个非常描述性的代码,因为我们现在知道我们有一个格式化程序,我们现在知道每个格式化程序必须能够做什么。
还有一个非常重要的主题是文档(至少对某些人来说…)。在您的文档中,您可能希望在子类中解释Formatter实际上是什么。有一个抽象类Formatter非常方便,您可以链接到子类中的文档。这是非常方便和通用的。另一方面,如果您没有抽象类Formatter,而只有接口IFormatter,则必须在每个子类中解释Formatter实际上是什么,因为接口是一个契约,你不会在接口的文档中描述Formatter实际上是什么-至少这不是常见的事情,你会打破大多数开发人员认为正确的语义。
注意:使抽象类实现接口是一种非常常见的模式。
要点:
抽象类可以具有属性、数据字段、方法(完整/不完整)。如果方法或财产在抽象关键字中定义,则必须在派生类中重写该关键字。(它作为一个紧密耦合的功能)如果为抽象类中的方法或财产定义抽象关键字,则无法定义方法体和获取/设置的值必须在派生类中重写的财产。抽象类不支持多重继承。抽象类包含构造函数。抽象类可以包含子、函数和财产的访问修饰符。只有抽象类的完整成员可以是静态的。接口只能从另一个接口继承,不能从抽象类继承,其中抽象类可以从另一抽象类或其他接口继承。
优势:
它是一种强制所有子类执行相同层次结构或标准的契约。如果各种实现都是相同的类型,并且使用共同的行为或状态,那么抽象类更适合使用。如果我们向抽象类添加一个新方法,那么我们可以选择提供默认实现,因此所有现有代码都可以正常工作。它允许比接口更快的执行。(接口需要更多时间在相应的类中查找实际方法。)它可以用于紧耦合和松耦合。
在此处查找详细信息。。。http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/
可以在此处找到解释:http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
抽象类是一个仅部分由程序员它可能包含一个或多个抽象方法。抽象方法只是一个函数定义用于告诉程序员方法必须在子级中实现班接口类似于抽象班实际上,接口占据了与类和抽象名称空间相同类。因此,您不能定义具有相同名称的接口作为一个班级。接口是一个完整的抽象类;没有一种方法实现,而不是类从中派生出来,据说实现该接口。
无论如何,我觉得这个接口的解释有些混乱。更常见的定义是:接口定义实现类必须履行的契约。接口定义由公共成员的签名组成,没有任何实现代码。
接口
接口是一个契约:编写接口的人说,“嘿,我接受这样的东西”,而使用接口的人则说“好的,我编写的类是这样的”。
接口是一个空壳。只有方法的签名,这意味着方法没有主体。接口无法执行任何操作。这只是一种模式。
例如(伪代码):
// I say all motor vehicles should look like this:
interface MotorVehicle
{
void run();
int getFuel();
}
// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{
int fuel;
void run()
{
print("Wrroooooooom");
}
int getFuel()
{
return this.fuel;
}
}
实现一个接口只消耗很少的CPU,因为它不是一个类,只是一堆名称,因此不需要进行任何昂贵的查找。在重要的时候,比如在嵌入式设备中,这是非常棒的。
抽象类
与接口不同,抽象类是类。它们的使用成本更高,因为从它们继承时需要进行查找。
抽象类看起来很像接口,但它们有更多:您可以为它们定义行为。这更像是一个人说,“这些课程应该看起来像那样,而且它们有共同点,所以填空吧!”。
例如:
// I say all motor vehicles should look like this:
abstract class MotorVehicle
{
int fuel;
// They ALL have fuel, so lets implement this for everybody.
int getFuel()
{
return this.fuel;
}
// That can be very different, force them to provide their
// own implementation.
abstract void run();
}
// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
void run()
{
print("Wrroooooooom");
}
}
实施
虽然抽象类和接口被认为是不同的概念,但实现有时会使该语句不真实。有时,他们甚至不是你想象的那样。
在Java中,这个规则是强制执行的,而在PHP中,接口是没有声明方法的抽象类。
在Python中,抽象类更多地是一种编程技巧,您可以从ABC模块中获得,并且实际上使用元类,因此使用类。接口与这种语言中的duck类型更为相关,它混合了约定和调用描述符的特殊方法(__method__方法)。
与编程一样,还有另一种语言的理论、实践和实践:-)
界面:转弯(左转,右转)
抽象类:轮子。
类别:方向盘,衍生自方向盘,暴露接口转向
一个是对可以在各种各样的事物中提供的行为进行分类,另一个是为事物本体建模。