e-s*_*tis 2196
接口是一个契约:编写界面的人说:" 嘿,我接受看起来那样的东西 ",使用界面的人说" 好吧,我写的课看起来那样 ".
接口是一个空壳.只有方法的签名,这意味着方法没有正文.界面无能为力.这只是一种模式.
例如(伪代码):
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
实现一个接口消耗很少的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");
}
}
Run Code Online (Sandbox Code Playgroud)
虽然抽象类和接口应该是不同的概念,但实现使得该语句有时不真实.有时,它们甚至不是你认为的那样.
在Java中,强制执行此规则,而在PHP中,接口是没有声明方法的抽象类.
在Python中,抽象类更多是您可以从ABC模块获得的编程技巧,实际上是使用元类,因此也是类.接口与这种语言中的duck typing更相关,它是约定和调用描述符的特殊方法(__method__方法)之间的混合.
与编程一样,有另一种语言的理论,实践和实践:-)
Jus*_*son 847
抽象类可以有常量,成员,方法存根(没有主体的方法)和定义的方法,而接口只能有常量和方法存根.
可以使用任何可见性定义抽象类的方法和成员,而接口的所有方法都必须定义为public
(默认情况下将它们定义为public).
继承抽象类时,具体子类必须定义抽象方法,而抽象类可以扩展另一个抽象类,而不必定义父类中的抽象方法.
类似地,扩展另一个接口的接口不负责从父接口实现方法.这是因为接口无法定义任何实现.
子类只能扩展单个类(抽象或具体),而接口可以扩展,或者类可以实现多个其他接口.
子类可以定义具有相同或更少限制的可见性的抽象方法,而实现接口的类必须定义具有完全相同的可见性(公共)的方法.
Viv*_*vek 137
An Interface contains only the definition/signature of functionality, and if we have some common functionality as well as common signatures, then we need to use an abstract class. By using an abstract class, we can provide behavior as well as functionality both in the same time. Another developer inheriting abstract class can use this functionality easily, as they would only need to fill in the blanks.
http://www.dotnetbull.com/2011/11/difference-between-abstract-class-and.html
http://www.dotnetbull.com/2011/11/what-is-abstract-class-in-c-net.html http://www.dotnetbull.com/2011/11/what-is-interface-in-c-net.html
Kon*_*man 80
可以在这里找到解释:http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
抽象类是一个仅由程序员部分实现的类.它可能包含一个或多个抽象方法.抽象方法只是一个函数定义,用于告诉程序员该方法必须在子类中实现.
接口类似于抽象类; 实际上,接口占用与类和抽象类相同的名称空间.因此,您无法定义与类同名的接口.接口是一个完全抽象的类; 没有任何方法被实现,而是从它的类子类,它被称为实现该接口.
无论如何,我发现接口的这种解释有点令人困惑.更常见的定义是:接口定义实现类必须满足的合同.接口定义由公共成员的签名组成,没有任何实现代码.
Rav*_*abu 39
我不想强调差异,这些差异已在许多答案中说过(关于接口中变量的公共静态最终修饰符以及对抽象类中受保护的私有方法的支持)
简单来说,我想说:
interface:通过多个不相关的对象实现合同
抽象类:在多个相关对象之间实现相同或不同的行为
来自Oracle 文档
考虑使用抽象类,如果:
考虑使用接口:
Serializable
接口.抽象类与具体类建立"是一种"关系.interface为类提供"具有"功能.
如果您正在寻找Java
编程语言,这里还有一些更新:
Java 8 通过提供方法功能在一定程度上缩小了类interface
和abstract
类之间的差距default
.接口没有方法的实现现在不再有效.
有关更多详细信息,请参阅此文档页面.
看看这个SE问题,以便更好地理解代码示例.
我该如何解释Interface和Abstract类之间的区别?
sof*_*e99 38
一些重要的区别:
以表格的形式:
1.主要区别是Java接口的方法是隐式抽象的,不能有实现.Java抽象类可以具有实现默认行为的实例方法.
2.在Java接口中声明的变量默认为final.抽象类可能包含非最终变量.
3.默认情况下,Java接口的成员是公共的.Java抽象类可以具有类似私有,受保护等类通常的类成员.
4.Java接口应该使用关键字"implements"来实现; 应使用关键字"extends"扩展Java抽象类.
5.接口只能扩展另一个Java接口,抽象类可以扩展另一个Java类并实现多个Java接口.
6. Java类可以实现多个接口,但它只能扩展一个抽象类.
7.Interface是绝对抽象的,无法实例化; Java抽象类也无法实例化,但如果存在main(),则可以调用它.
8.与java抽象类相比,java接口很慢,因为它需要额外的间接.
小智 30
重点是:
Jai*_*der 24
我正在建造一个300层的建筑
建筑的蓝图界面
建筑物最多可容纳200层 - 部分完工 - 抽象
建筑施工完成 - 混凝土
接口
抽象
取自DurgaJobs网站
Dha*_*jay 18
让我们再次讨论这个问题:
让你知道的第一件事是1/1和1*1会产生相同的结果,但这并不意味着乘法和除法是相同的.显然,他们保持着良好的关系,但请注意,两者都是不同的.
我将指出主要的不同之处,其余的已经解释过了:
抽象类对于建立类层次结构非常有用.乍一看任何要求,我们都清楚地知道要构建什么,但我们知道要构建什么.所以你的抽象类是你的基类.
接口对于让其他层次结构或类知道我能够做什么很有用.当你说我有能力时,你必须具备这种能力.接口将标记为类必须实现相同的功能.
g00*_*ur3 12
实际上它非常简单.
您可以将接口视为一个类,只允许使用抽象方法而不允许其他方法.
因此,接口只能"声明"而不能定义您希望类具有的行为.
抽象类允许您同时声明(使用抽象方法)以及定义(使用完整方法实现)您希望类具有的行为.
普通类只允许您定义,而不是声明您希望类具有的行为/操作.
最后一件事,
在Java中,您可以实现多个接口,但是您只能扩展一个(抽象类或类)...
这意味着定义行为的继承被限制为只允许每个类一个...即如果你想要一个封装了A,B和C类行为的类,你需要执行以下操作:类A扩展B,类C扩展A ..它有点关于多重继承的方法......
另一方面,接口可以简单地做:接口C实现A,B
所以实际上Java只在"声明的行为"即接口中支持多重继承,并且只支持具有已定义行为的单继承..除非你按照我描述的方式进行循环...
希望这是有道理的.
yeg*_*256 11
接口与抽象类的比较是错误的.应该有另外两个比较:1)接口与类和2)抽象与最终类.
接口是两个对象之间的契约.例如,我是邮差,你是一个提供的套餐.我希望你知道你的送货地址.当有人给我一个包裹时,它必须知道它的送货地址:
interface Package {
String address();
}
Run Code Online (Sandbox Code Playgroud)
类是遵守合同的一组对象.例如,我是"Box"组的一个盒子,我遵守邮递员要求的合同.同时我遵守其他合同:
class Box implements Package, Property {
@Override
String address() {
return "5th Street, New York, NY";
}
@Override
Human owner() {
// this method is part of another contract
}
}
Run Code Online (Sandbox Code Playgroud)
抽象类是一组不完整的对象.他们不能使用,因为他们错过了一些部分.例如,我是一个抽象的GPS感知框 - 我知道如何检查我在地图上的位置:
abstract class GpsBox implements Package {
@Override
public abstract String address();
protected Coordinates whereAmI() {
// connect to GPS and return my current position
}
}
Run Code Online (Sandbox Code Playgroud)
如果由另一个类继承/扩展,该类可能非常有用.但它本身 - 它没用,因为它不能有物体.抽象类可以构建最终类的元素.
最终类是一组完整的对象,可以使用,但不能修改.他们确切知道如何工作和做什么.例如,我是一个总是进入其构造期间指定的地址的Box:
final class DirectBox implements Package {
private final String to;
public DirectBox(String addr) {
this.to = addr;
}
@Override
public String address() {
return this.to;
}
}
Run Code Online (Sandbox Code Playgroud)
在大多数语言中,如Java或C++,可能只有一个类,既不是抽象的也不是最终的.这样的类可以继承并可以实例化.但我并不认为这严格符合面向对象的范式.
同样,将接口与抽象类进行比较是不正确的.
唯一的区别是,一个人可以参与多重继承,而另一个则不能.
接口的定义随着时间的推移而发生了变化.你认为一个接口只有方法声明而且只是合同吗?那么静态最终变量以及Java 8之后的默认定义呢?
由于具有多重继承的钻石问题,接口被引入Java ,这就是他们实际打算做的事情.
接口是为了避免多重继承问题而创建的构造,可以包含抽象方法,默认定义和静态最终变量.
简而言之,差异如下:
接口和抽象类之间的语法差异:
现在在Interfaces中:
public static
- 支持
public abstract
- 支持
public default
- 支持
private static
- 支持
private abstract
- 编译错误
private default
- 编译错误
private
- 支持
我迟到了 10 年,但我想尝试任何方式。几天前写了一篇关于同样内容的文章。想到将其发布在这里。
\n\n太长;博士;当您看到 \xe2\x80\x9cIs A\xe2\x80\x9d 关系时,使用继承/抽象类。当您看到 \xe2\x80\x9chas a\xe2\x80\x9d 关系时创建成员变量。当您看到 \xe2\x80\x9crelies on externalprovider\xe2\x80\x9d 时,实现(而不是继承)一个接口。
\n\n面试问题:接口和抽象类有什么区别?你如何决定何时使用什么? \n我大多得到以下一个或全部答案:\n答案 1:你不能创建抽象类和接口的对象。
\n\nZK(That\xe2\x80\x99是我名字的缩写):你不能创建其中任何一个的对象。所以这没有区别。这是接口和抽象类之间的相似之处。计数器\n问题:为什么\xe2\x80\x99不能创建抽象类或接口的对象?
\n\n答案 2:抽象类可以有一个函数体作为部分/默认实现。
\n\nZK:反问:所以如果我将其更改为纯抽象类,将所有虚函数标记为抽象,并且不为任何虚函数提供默认实现。这会使抽象类和接口相同吗?之后它们可以互换使用吗?
\n\n答案3:接口允许多继承和抽象类don\xe2\x80\x99t。
\n\nZK:反问:你真的继承了接口吗?或者您只是实现一个接口并从抽象类继承?\xe2\x80\x99 实现和继承之间有什么区别?\n这些反问问题让考生摸不着头脑,或者干脆直接进入下一个问题。这让我认为人们需要有关面向对象编程的这些基本构建块的帮助。\n原始问题和所有反问题的答案都可以在英语和 UML 中找到。\n您必须至少了解以下内容才能理解这些两个结构更好。
\n\n普通名词:普通名词是对同类或同类事物赋予 \xe2\x80\x9cin common\xe2\x80\x9d 的名称。例如水果、动物、城市、汽车等。
\n\n专有名词:专有名词是物体、地点或事物的名称。苹果、卡特彼勒、纽约、本田雅阁等
\n\n汽车是一个普通名词。本田雅阁是一个专有名词,并且可能是一个复合专有名词,一个使用两个名词组成的专有名词。
\n\n来到 UML 部分。您应该熟悉以下关系:
\n\n让\xe2\x80\x99s 考虑下面两个句子。\n- HondaAccord 是一辆汽车吗?\n- HondaAccord 有一辆汽车吗?
\n\n哪一个听起来正确?简单的英语和理解能力。HondaAccord 和 Cars 共享 \xe2\x80\x9cIs A\xe2\x80\x9d 关系。本田雅阁没有\xe2\x80\x99t里面有车。它\xe2\x80\x9是一辆\xe2\x80\x9d汽车。Honda Accord \xe2\x80\x9chas 里面有一个 \xe2\x80\x9d 音乐播放器。
\n\n当两个实体共享\xe2\x80\x9c是一个\xe2\x80\x9d关系时,\xe2\x80\x99是更好的继承候选者。Has a 关系是创建成员变量的更好候选者。\n建立此关系后,我们的代码如下所示:
\n\nabstract class Car\n{\n string color;\n int speed;\n}\nclass HondaAccord : Car\n{\n MusicPlayer musicPlayer;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n现在本田不生产音乐播放器。或者至少\xe2\x80\x99不是他们的主要业务。
\n\n于是他们联系其他公司并签订了合同。如果您在这里接收电源并在这两条线上接收输出信号,则它\xe2\x80\x99将在这些扬声器上正常播放。
\n\n这使得音乐播放器成为界面的完美候选者。只要连接工作正常,您\xe2\x80\x99 并不关心谁为其提供支持。
\n\n您可以将 LG 的 MusicPlayer 替换为 Sony 或其他方式。它不会改变本田雅阁的任何东西。
\n\n为什么\xe2\x80\x99不能创建抽象类的对象?
\n\n因为你不能\xe2\x80\x99走进陈列室并说给我一辆车。你\xe2\x80\x99必须提供一个专有名词。什么车?应该是本田雅阁吧 当销售代理可以为您提供一些东西时\xe2\x80\x99s。
\n\n为什么\xe2\x80\x99不能创建接口的对象?\n因为你不能\xe2\x80\x99走进陈列室并说给我一份音乐播放器合同。它不会\xe2\x80\x99 帮助。消费者和提供商之间的接口只是为了促进达成协议。您将如何处理协议副本?它不会\xe2\x80\x99 播放音乐。
\n\n为什么接口允许多重继承?
\n\n接口不是继承的。接口已实现。\n接口是与外部世界交互的候选接口。\n本田雅阁有一个加油接口。它具有用于给轮胎充气的接口。以及用于给足球充气的同一软管。所以新代码如下所示:
\n\nabstract class Car\n{\n string color;\n int speed;\n}\nclass HondaAccord : Car, IInflateAir, IRefueling\n{\n MusicPlayer musicPlayer;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n而英文会这样写\xe2\x80\x9c本田雅阁是一款支持轮胎充气和加油的汽车\xe2\x80\x9d。
\n这并不是原始问题的答案,但一旦你找到了它们之间差异的答案,你就会进入何时使用的困境: 何时使用接口或抽象类?何时同时使用两者?
我对 OOP 的了解有限,但到目前为止,将接口视为语法中形容词的等价物对我来说一直有效(如果这个方法是假的,请纠正我!)。例如,接口名称就像您可以赋予类的属性或功能,并且一个类可以拥有其中许多属性或功能:ISerialized、ICountable、IList、ICacheable、IHappy,...
如果您有一些可供多个类使用的常用方法,请转到抽象类.否则,如果您希望这些类遵循一些明确的蓝图,请转到接口.
以下示例证明了这一点
Java中的抽象类:
abstract class animals
{
// They all love to eat. So let's implement them for everybody
void eat()
{
System.out.println("Eating...");
}
// The make different sounds. They will provide their own implementation.
abstract void sound();
}
class dog extends animals
{
void sound()
{
System.out.println("Woof Woof");
}
}
class cat extends animals
{
void sound()
{
System.out.println("Meoww");
}
}
Run Code Online (Sandbox Code Playgroud)
以下是Java中的接口实现:
interface Shape
{
void display();
double area();
}
class Rectangle implements Shape
{
int length, width;
Rectangle(int length, int width)
{
this.length = length;
this.width = width;
}
@Override
public void display()
{
System.out.println("****\n* *\n* *\n****");
}
@Override
public double area()
{
return (double)(length*width);
}
}
class Circle implements Shape
{
double pi = 3.14;
int radius;
Circle(int radius)
{
this.radius = radius;
}
@Override
public void display()
{
System.out.println("O"); // :P
}
@Override
public double area()
{
return (double)((pi*radius*radius)/2);
}
}
Run Code Online (Sandbox Code Playgroud)
简而言之,一些重要的关键点:
Java界面中声明的变量默认为final.抽象类可以包含非最终变量.
Java接口中声明的变量默认为static.抽象类可以有非静态变量.
默认情况下,Java接口的成员是公共的.Java抽象类可以具有类似私有,受保护等类通常的类成员.
关键点:
优势:
在这里找到详细信息... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/
最简单的总结就是 aninterface
是:
default
和static
方法;虽然它有default
和static
方法的定义(方法签名+实现),但它只有其他方法的声明(方法签名)。interface
s,并且一个interface
可以从多个 s 继承interface
)。所有变量都是隐式常量,无论public static final
是否指定为。所有成员都是隐式的public
,无论是否指定。同时,一个abstract
类是:
abstract
方法。可以包含声明和定义,声明标记为abstract
.protected
、private
、 或私有包(未指定)。或者,如果我们想将其全部归结为一句话:Aninterface
是实现类所拥有的,而类则abstract
是子类所拥有的。
许多初级开发人员错误地将接口、抽象类和具体类视为同一事物的微小变体,并纯粹出于技术原因选择其中之一:我需要多重继承吗?我需要一些地方来放置常用方法吗?除了具体的课程之外,我还需要费心吗?这是错误的,隐藏在这些问题中的是主要问题:“我”。当您为自己编写代码时,您很少会想到其他现在或未来的开发人员正在处理您的代码或使用您的代码。
接口和抽象类,虽然从技术角度看很相似,但具有完全不同的含义和目的。
接口定义了一些实现将为您履行的契约。
抽象类提供了一个默认的行为是您的实现可以重复使用。
具体的类以非常具体的方式完成实际工作。例如,anArrayList
使用连续的内存区域以紧凑的方式存储对象列表,提供快速的随机访问、迭代和就地更改,但在插入、删除和偶尔添加时很糟糕;同时,aLinkedList
使用双链接节点来存储对象列表,它提供快速迭代、就地更改和插入/删除/添加,但在随机访问时很糟糕。这两种类型的列表针对不同的用例进行了优化,您将如何使用它们很重要。当您试图从与您大量交互的列表中挤出性能时,并且选择列表类型取决于您时,您应该仔细选择您正在实例化的列表。
另一方面,列表的高级用户并不真正关心它是如何实际实现的,他们应该与这些细节隔离开来。让我们想象一下 Java 没有公开List
接口,但只有一个具体的List
类,这实际上LinkedList
是现在的样子。所有 Java 开发人员都会调整他们的代码以适应实现细节:避免随机访问,添加缓存以加快访问速度,或者只是ArrayList
自己重新实现,尽管它会与所有其他实际List
只使用的代码不兼容。那会很糟糕……但是现在想象一下,Java 大师实际上意识到链表对于大多数实际用例来说很糟糕,并决定切换到数组列表作为他们唯一的选择List
类可用。这会影响世界上每个 Java 程序的性能,人们不会对此感到高兴。罪魁祸首是实现细节是可用的,开发人员认为这些细节是他们可以依赖的永久合同。这就是为什么隐藏实现细节并且只定义抽象契约很重要的原因。这就是接口的目的:定义一个方法接受什么样的输入,以及预期什么样的输出,而不会暴露所有的胆量,这些胆量会诱使程序员调整他们的代码以适应可能随着任何未来更新而改变的内部细节.
抽象类介于接口和具体类之间。它应该帮助实现共享常见或无聊的代码。例如,AbstractCollection
提供了isEmpty
基于大小为 0、contains
迭代和比较、addAll
重复等的基本实现add
。这让实现专注于区分它们的关键部分:如何实际存储和检索数据。
接口是代码不同部分之间的低内聚网关。它们允许图书馆存在和发展,而不会在内部发生变化时破坏每个图书馆用户。它被称为应用程序编程接口,而不是应用程序编程类。在较小的规模上,它们还允许多个开发人员在大型项目上成功协作,方法是通过记录良好的接口分离不同的模块。
抽象类是在实现接口时使用的高内聚帮助器,假设有一定程度的实现细节。或者,抽象类用于定义 SPI、服务提供者接口。
API 和 SPI 之间的区别很微妙,但很重要:对于 API 而言,重点在于谁使用它,而对于 SPI,重点在于谁实现了它。
向 API 添加方法很容易,API 的所有现有用户仍将编译。向 SPI 添加方法很困难,因为每个服务提供者(具体实现)都必须实现新方法。如果使用接口来定义 SPI,则每当 SPI 合同发生变化时,提供者都必须发布新版本。如果改为使用抽象类,新方法可以根据现有抽象方法定义,也可以定义为空throw not implemented exception
存根,这至少允许旧版本的服务实现仍然编译和运行。
尽管 Java 8 为接口引入了默认方法,这使得接口和抽象类之间的界限更加模糊,但这并不是为了让实现可以重用代码,而是为了更容易地更改既用作 API 又用作 SPI 的接口(或错误地用于定义 SPI 而不是抽象类)。
一个推论:反过来往往是错误的:在使用thing 时,总是尝试使用您实际需要的最通用的类/接口。换句话说,不要将您的变量声明为ArrayList theList = new ArrayList()
,除非您实际上非常依赖它是一个数组列表,并且没有其他类型的列表会为您削减它。使用List theList = new ArrayList
替代,甚至Collection theCollection = new ArrayList
如果一个事实,即它是一个列表,而不是任何其他类型的集合实际上没有问题。
小智 5
您可以找到接口和抽象类之间的明显区别。
界面
抽象类
抽象类包含抽象方法和非抽象方法。
继承抽象类时不强制用户实现所有方法。
包含各种变量,包括原始变量和非原始变量
使用抽象关键字声明。
抽象类的方法和成员可以定义为任何可见性。
一个子类只能扩展一个类(抽象或具体)。
归档时间: |
|
查看次数: |
1233551 次 |
最近记录: |