接口和抽象类之间到底有什么区别?
当前回答
一些重要的区别:
以表格的形式:
正如Joe在javapapers中所说:
1.主要区别在于Java接口的方法是隐式抽象的,不能有实现。Java抽象类可以具有实现默认行为的实例方法。2.Java接口中声明的变量默认为final。抽象类可以包含非最终变量。3.默认情况下,Java接口的成员是公共的。Java抽象类可以具有类成员的通常风格,受保护等。。4.Java接口应使用关键字“implements”实现;Java抽象类应该使用关键字“extends”进行扩展。5.接口只能扩展另一个Java接口,抽象类可以扩展另一Java类并实现多个Java接口。6.Java类可以实现多个接口,但只能扩展一个抽象类。7.接口是绝对抽象的,不能实例化;Java抽象类也不能实例化,但如果main()存在。8.与java抽象类相比,java接口速度较慢,因为它需要额外的间接寻址。
其他回答
抽象类是无法创建对象的类或无法实例化的类。抽象方法使类抽象。抽象类需要被继承,以便覆盖在抽象类中声明的方法。对访问说明符没有限制。抽象类中可以有构造函数和其他具体(非abstract方法)方法,但接口不能有。
接口是方法的蓝图/模板。(例如,在纸上给出一个房子(接口房子),不同的建筑师将使用他们的想法来建造它(实现房子接口的建筑师的类别)。它是抽象方法、默认方法、静态方法、最终变量和嵌套类的集合。所有成员都将是最终成员或公共成员,不允许使用受保护和私有访问说明符。不允许创建对象。必须创建一个类,以便使用实现接口并重写接口中声明的抽象方法。接口是松散耦合(动态多态性/动态绑定)的一个很好的例子接口实现了多态性和抽象。它告诉要做什么,但如何做由实现类定义。例如,有一家汽车公司希望其制造的所有汽车的某些功能都相同,因此该公司将制造一种具有这些功能的接口车辆,而不同级别的汽车(如Maruti Suzkhi、Maruti 800)将覆盖这些功能。
当我们已经有抽象类时,为什么要接口?Java只支持多级和分层继承,但借助于接口,我们可以实现多重继承。
许多初级开发人员错误地将接口、抽象类和具体类视为同一事物的细微变化,并纯粹基于技术原因选择其中之一:我需要多重继承吗?我需要一些地方来放置常用方法吗?除了一堂具体的课,我还需要为别的事情而烦恼吗?这是错误的,隐藏在这些问题中的是主要问题:“我”。当你自己编写代码时,你很少想到其他现在或将来的开发人员正在处理或使用你的代码。
接口和抽象类,虽然从技术角度看很相似,但有着完全不同的含义和目的。
总结
接口定义了某个实现将为您实现的契约。抽象类提供了您的实现可以重用的默认行为。
备选摘要
接口用于定义公共API抽象类用于内部使用和定义SPIs
隐藏实现细节的重要性
具体的类以非常具体的方式完成实际工作。例如,ArrayList使用一个连续的内存区域以紧凑的方式存储对象列表,这提供了快速的随机访问、迭代和就地更改,但在插入、删除和偶尔甚至添加时非常糟糕;同时,LinkedList使用双链接节点来存储对象列表,这提供了快速迭代、就地更改和插入/删除/添加,但在随机访问时非常糟糕。这两种列表针对不同的用例进行了优化,如何使用它们非常重要。当您试图从与您密切交互的列表中挤出性能时,当选择列表类型时,您应该仔细选择要实例化的列表。
另一方面,列表的高级用户并不真正关心它是如何实现的,他们应该与这些细节隔离开来。让我们想象一下,Java没有公开List接口,但只有一个具体的List类,这实际上就是LinkedList现在的样子。所有Java开发人员都会定制自己的代码以适应实现细节:避免随机访问,添加缓存以加快访问速度,或者自己重新实现ArrayList,尽管这与所有其他仅适用于List的代码不兼容。那太可怕了。。。但现在想象一下,Java主控实际上意识到链接列表对于大多数实际用例来说都是可怕的,并决定切换到数组列表,以获得唯一可用的list类。这将影响世界上每一个Java程序的性能,人们对此不会感到高兴。主要原因是实现细节是可用的,而开发人员认为这些细节是他们可以依赖的永久契约。这就是为什么隐藏实现细节,只定义抽象契约很重要。这就是接口的目的:定义一个方法接受什么样的输入,以及期望什么样的输出,而不暴露所有可能诱使程序员调整代码以适应未来任何更新可能改变的内部细节的勇气。
抽象类位于接口和具体类之间。它应该帮助实现共享公共或无聊的代码。例如,AbstractCollection提供了基于大小为0的isEmpty的基本实现,包含作为迭代和比较,addAll作为重复添加等等。这让实现专注于区分它们的关键部分:如何实际存储和检索数据。
API与SPI
接口是代码不同部分之间的低内聚网关。它们允许图书馆存在和发展,而不会在内部发生变化时破坏每个图书馆用户。它叫做应用程序编程接口,而不是应用程序编程类。在较小的规模上,它们还允许多个开发人员在大型项目上成功协作,通过文档化的界面将不同的模块分离。
抽象类是在实现接口时使用的高内聚性帮助程序,假定实现细节级别。或者,抽象类用于定义SPI、服务提供商接口。
API和SPI之间的区别很细微,但很重要:对于API,重点是谁使用它,而对于SPI,重点是由谁实现它。
向API添加方法很容易,API的所有现有用户仍将编译。向SPI添加方法很难,因为每个服务提供商(具体实现)都必须实现新方法。如果使用接口定义SPI,则每当SPI合约发生变化时,提供商都必须发布新版本。如果改用抽象类,则可以根据现有的抽象方法定义新方法,或者将新方法定义为空抛出未实现的异常存根,这至少允许旧版本的服务实现仍然编译和运行。
关于Java 8和默认方法的说明
虽然Java8引入了接口的默认方法,这使得接口和抽象类之间的界限更加模糊,但这并不是为了实现可以重用代码,而是为了更容易地更改同时用作API和SPI的接口(或者错误地用于定义SPI而不是抽象类)。
使用哪一个?
这个东西应该由代码的其他部分或其他外部代码公开使用吗?向其添加一个接口,以从公共抽象契约中隐藏实现细节,这是该事物的一般行为。这件事是不是应该有多个实现,有很多共同的代码?既要做一个接口,又要做一个抽象的、不完整的实现。是否只有一个实现,而没有其他人会使用它?让它成为一个具体的课程。“ever”是一个很长的时间,你可以安全地使用它,并在它上面添加一个界面。
一个推论:另一种方法往往是错误的:当使用一个东西时,总是尝试使用您实际需要的最通用的类/接口。换句话说,不要将变量声明为ArrayListtheList=newArrayList(),除非您实际上对它是一个数组列表有很强的依赖性,并且没有其他类型的列表可以为您删除它。如果它是一个列表,而不是任何其他类型的集合这一事实实际上无关紧要,请改用ListtheList=newArrayList,甚至使用CollectiontheCollection=newArrayNist。
接口
接口是一个契约:编写接口的人说,“嘿,我接受这样的东西”,而使用接口的人则说“好的,我编写的类是这样的”。
接口是一个空壳。只有方法的签名,这意味着方法没有主体。接口无法执行任何操作。这只是一种模式。
例如(伪代码):
// 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__方法)。
与编程一样,还有另一种语言的理论、实践和实践:-)
可以在此处找到解释:http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
抽象类是一个仅部分由程序员它可能包含一个或多个抽象方法。抽象方法只是一个函数定义用于告诉程序员方法必须在子级中实现班接口类似于抽象班实际上,接口占据了与类和抽象名称空间相同类。因此,您不能定义具有相同名称的接口作为一个班级。接口是一个完整的抽象类;没有一种方法实现,而不是类从中派生出来,据说实现该接口。
无论如何,我觉得这个接口的解释有些混乱。更常见的定义是:接口定义实现类必须履行的契约。接口定义由公共成员的签名组成,没有任何实现代码。
这里是对接口与抽象类的一个非常基本的理解。
推荐文章
- Java抽象接口
- 什么是依赖倒置原则?为什么它很重要?
- 为什么在Python方法中需要显式地有“self”参数?
- 如何在方法中访问“静态”类变量?
- 为什么c#不提供c++风格的'friend'关键字?
- String, StringBuffer和StringBuilder
- 如何在python抽象类中创建抽象属性?
- 存储库和服务层的区别?
- DDD -实体不能直接访问存储库的规则
- 为什么STL如此严重地基于模板而不是继承?
- 如何在Objective-C中声明类级属性?
- 面向方面编程与面向对象编程
- c++中类似于java的instanceof
- 在python中遍历对象属性
- 将类代码分离为头文件和cpp文件