接口和抽象类之间到底有什么区别?
接口和抽象类之间到底有什么区别?
Answers:
接口是一种契约:编写接口的人说:“ 嘿,我接受那样的事情 ”,而使用接口的人说:“ 好,我编写的类看起来就这样 ”。
接口是一个空壳。这些方法只有签名,这意味着这些方法没有主体。该界面无法执行任何操作。这只是一个模式。
例如(伪代码):
// 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模块获得的编程技巧,实际上是在使用元类,因此也使用类。接口与这种语言中的鸭子类型更相关,它是约定和调用描述符的特殊方法(__method__方法)之间的混合。
和编程一样,理论,实践和实践都是另一种语言:-)
interface
,并class
从Head First Java
生动的是A class defines who you are, and an interface tells what roles you could play
抽象类可以具有常量,成员,方法存根(没有主体的方法)和已定义的方法,而接口只能具有常量和方法存根。
可以以任何可见性定义抽象类的方法和成员,而接口的所有方法都必须定义为public
(默认情况下,它们被定义为public)。
在继承抽象类时,具体的子类必须定义抽象方法,而抽象类可以扩展另一个抽象类,而不必定义父类的抽象方法。
同样,扩展另一个接口的接口也不负责从父接口实现方法。这是因为接口无法定义任何实现。
子类只能扩展一个类(抽象或具体),而一个接口可以扩展或一个类可以实现多个其他接口。
子类可以定义具有相同或更少限制性可见性的抽象方法,而实现接口的类必须定义具有完全相同的可见性(公共)的方法。
CANNOT
要实例化的抽象类不同。
接口仅包含功能的定义/签名,如果我们具有一些通用功能和通用签名,则需要使用抽象类。通过使用抽象类,我们可以同时提供行为和功能。另一个继承抽象类的开发人员可以轻松使用此功能,因为他们只需要填写空白即可。
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
可以在这里找到说明:http : //www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
抽象类是仅由程序员部分实现的类。它可能包含一个或多个抽象方法。抽象方法只是一个函数定义,用于告诉程序员该方法必须在子类中实现。
接口类似于抽象类。实际上,接口与类和抽象类占用相同的名称空间。因此,您不能定义与类同名的接口。接口是一个完全抽象的类;它的任何方法均未实现,并且据说不是从该方法子类继承而来,而是实现了该接口。
无论如何,我发现对接口的这种解释有些令人困惑。一个更常见的定义是:接口定义实现类必须满足的协定。接口定义由公共成员的签名组成,没有任何实现代码。
我不想强调差异,在许多答案中已经提到了差异(关于接口中变量的公共静态最终修饰符以及对抽象类中受保护的私有方法的支持)
简单来说,我想说:
接口:由多个不相关的对象实施合同
抽象类:在多个相关对象之间实现相同或不同的行为
从Oracle 文档
如果满足以下条件,请考虑使用抽象类:
如果满足以下条件,请考虑使用接口:
Serializable
接口。抽象类与具体类建立“是”关系。接口为类提供“具有”功能。
如果您正在寻找 Java
编程语言,这里还有更多更新:
爪哇8具有降低之间的间隙interface
和abstract
通过提供一类在一定程度上default
的方法的特征。接口没有实现的方法不再有效。
请参阅此文档页面有关更多详细信息,。
请看一下这个SE问题,以获取更好的代码示例。
一些重要的区别:
以表格的形式:
1.主要区别在于Java接口的方法是隐式抽象的,无法实现。Java抽象类可以具有实现默认行为的实例方法。
2. Java接口中声明的变量默认为final。抽象类可能包含非最终变量。
3. Java接口的成员默认情况下是公共的。Java抽象类可以具有类成员的常用风格,例如private,protected等。
4.Java接口应使用关键字“ implements”来实现;Java抽象类应使用关键字“ extends”进行扩展。
5.一个接口只能扩展另一个Java接口,一个抽象类可以扩展另一个Java类并实现多个Java接口。
6.Java类可以实现多个接口,但只能扩展一个抽象类。
7,接口绝对是抽象的,不能实例化;Java抽象类也无法实例化,但是可以在存在main()的情况下调用。
8,与Java抽象类相比,Java接口比较慢,因为它需要额外的间接调用。
要点是:
我正在建造一个300层的建筑物
建筑物的蓝图界面
建筑高达200层-部分完成--- 摘要
建筑施工完成- 混凝土
接口
抽象
取自DurgaJobs网站
让我们再次解决这个问题:
首先要知道的是1/1和1 * 1的结果相同,但这并不意味着乘法和除法相同。显然,他们之间保持着良好的关系,但是请注意你们俩是不同的。
我将指出主要的区别,其余的都已经解释了:
抽象类对于建模类层次结构很有用。在任何要求乍看之下,我们是在什么部分澄清究竟是要建,但我们知道什么来构建。因此,您的抽象类就是您的基类。
接口可用于让其他层次结构或类知道我的能力。当你说我有能力的时候,你必须具备这种能力。接口会将其标记为类必须实施相同的功能。
实际上,这非常简单。
您可以将接口视为只允许使用抽象方法而没有其他东西的类。
因此,接口只能“声明”,而不能定义您希望类具有的行为。
抽象类使您既可以声明(使用抽象方法)也可以定义(使用完整方法实现)想要类具有的行为。
常规类仅允许您定义而不是声明您希望类具有的行为/动作。
最后一件事,
在Java中,您可以实现多个接口,但只能扩展一个接口(抽象类或类)...
这意味着已定义行为的继承被限制为每个类只允许一个继承...即,如果您想要一个封装了来自类A,B&C的行为的类,则需要执行以下操作:类A扩展B,类C扩展A ..拥有多个继承的方式有点复杂...
另一方面,您可以简单地做到:接口C实现A,B
因此,实际上Java仅在“声明的行为”(即接口)中支持多重继承,而在定义的行为中仅支持单一继承..除非您按照我描述的方式进行操作...
希望这是有道理的。
接口与抽象类的比较是错误的。相反,应该进行另外两个比较:1)接口与类以及2)抽象与最终类。
接口是两个对象之间的契约。例如,我是一名邮递员,而您则是一个包裹。我希望您知道您的收货地址。当有人给我一个包裹时,它必须知道它的收货地址:
interface Package {
String address();
}
类是一组遵守合同的对象。例如,我是“盒子”组中的一个盒子,我遵守邮递员要求的合同。同时,我遵守其他合同:
class Box implements Package, Property {
@Override
String address() {
return "5th Street, New York, NY";
}
@Override
Human owner() {
// this method is part of another contract
}
}
抽象类是一组不完整的对象。它们无法使用,因为它们会遗漏某些零件。例如,我是一个抽象的GPS感知盒-我知道如何检查我在地图上的位置:
abstract class GpsBox implements Package {
@Override
public abstract String address();
protected Coordinates whereAmI() {
// connect to GPS and return my current position
}
}
如果该类被另一个类继承/扩展,则该类非常有用。但就其本身而言-它没有用,因为它没有对象。抽象类可以作为最终类的构建元素。
最终类是一组完整的对象,可以使用但不能修改。他们确切地知道如何工作和做什么。例如,我是一个箱子,总是去往构造期间指定的地址:
final class DirectBox implements Package {
private final String to;
public DirectBox(String addr) {
this.to = addr;
}
@Override
public String address() {
return this.to;
}
}
在大多数语言中,例如Java或C ++,可能只有一个类,既不是抽象类也不是final类。这样的类可以被继承并可以实例化。不过,我不认为这完全符合面向对象的范式。
同样,将接口与抽象类进行比较是不正确的。
简而言之,差异如下:
接口和抽象类之间的语法差异:
在现在的接口中:
public static
-支持
public abstract
-支持
public default
-支持
private static
-支持
private abstract
-编译错误
private default
-编译错误
private
-支持
唯一的区别是一个可以参与多重继承,而另一个则不能。
接口的定义已随时间而改变。您是否认为接口仅具有方法声明,而只是合同?静态最终变量如何?Java 8之后的默认定义如何?
接口是由于具有多重继承的钻石问题而引入Java的,而这正是它们实际要做的。
接口是为避免多重继承问题而创建的构造,可以具有抽象方法,默认定义和静态最终变量。
如果您有一些可以由多个类使用的通用方法,请使用抽象类。否则,如果您希望类遵循某些确定的蓝图,则可以使用接口。
以下示例说明了这一点。
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");
}
}
以下是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);
}
}
概括地说一些重要的要点:
在Java接口中声明的变量默认为final。抽象类可以具有非最终变量。
Java接口中声明的变量默认情况下是静态的。抽象类可以具有非静态变量。
默认情况下,Java接口的成员是公共的。Java抽象类可以具有类成员的常用风格,例如private,protected等。
许多初级开发人员会犯错误,认为接口,抽象类和具体类只是同一事物的细微变化,因此纯粹出于技术原因选择其中之一:我是否需要多重继承?我需要放置通用方法的地方吗?除了具体的课程外,我是否还需要打扰?这是错误的,隐藏在这些问题中的是主要问题:“ I”。当您自己编写代码时,很少会想到使用该代码或正在使用该代码的其他现在或将来的开发人员。
接口和抽象类,尽管从技术角度看显然是相似的,但它们的含义和目的却完全不同。
接口定义了一些实现将为您实现的合同。
抽象类提供了一个默认的行为是您的实现可以重复使用。
具体的类以非常特定的方式完成实际工作。例如,一个ArrayList
使用连续的内存区域以紧凑的方式存储对象列表,该列表提供快速的随机访问,迭代和就地更改,但是在插入,删除以及偶而添加时很糟糕;同时,LinkedList
使用双向链接节点存储对象列表,该对象列表提供快速迭代,就地更改以及插入/删除/添加,但在随机访问时非常糟糕。这两种类型的列表针对不同的用例进行了优化,因此如何使用它们非常重要。当您试图从与您进行大量交互的列表中挤出性能时,并且在选择适合您的列表类型时,您应该仔细选择要实例化的列表。
另一方面,列表的高级用户实际上并不关心列表的实际实现方式,因此应该与这些细节隔离。让我们想象一下,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而不是抽象类)。
一个必然的结论:相反的方法常常被错误地完成:在使用事物时,总是尝试使用实际需要的最通用的类/接口。换句话说,不要将变量声明为ArrayList theList = new ArrayList()
,除非您实际上非常依赖于它是数组列表,并且没有其他类型的列表会为您削减它。使用它List theList = new ArrayList
,或者即使Collection theCollection = new ArrayList
它是列表,而不是其他任何类型的集合,实际上都没有关系。
并不是真正的原始问题的答案,但是一旦您找到了它们之间的区别的答案,您将进入每种情况何时使用的难题: 什么时候使用接口或抽象类?何时同时使用?
我对OOP的了解有限,但是到目前为止,将接口视为语法中的形容词的等效项对我来说一直有效(如果此方法是伪造的,请改正我!)。例如,接口名称就像您可以为类赋予的属性或功能,并且一个类可以具有许多名称:ISerializable,ICountable,IList,ICacheable,IHappy等。
继承用于两个目的:
允许对象将父类型数据成员和方法实现视为自己的。
允许对一种类型的对象的引用被期望使用超类型对象的代码使用。
在支持广义多重继承的语言/框架中,通常几乎不需要将类型分类为“接口”或“抽象类”。但是,流行的语言和框架将允许一种类型将另一种类型的数据成员或方法实现视为其自身,即使它们允许一种类型可以替换为任意数量的其他类型。
抽象类可能具有数据成员和方法实现,但只能由不从任何其他类继承的类继承。接口几乎对实现它们的类型没有任何限制,但是不能包含任何数据成员或方法实现。
有时候,将类型替换为许多不同的东西很有用;在其他情况下,对象将父类型的数据成员和方法实现视为自己的对象很有用。在接口和抽象类之间进行区分可以在最相关的情况下使用每种功能。
关键点:
优点:
在此处找到详细信息... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/
概括起来最简单的方法interface
是:
default
和static
方法之外;它具有default
和static
方法的定义(方法签名+实现),而仅具有其他方法的声明(方法签名)。interface
s,而an interface
可以从多个interface
s 继承)。无论是否指定,所有变量都是隐式常量public static final
。public
无论是否指定,所有成员都是隐式的。同时,一个abstract
类是:
abstract
方法的趋势。可以包含声明和定义,声明标记为abstract
。protected
,private
或私有包(未指定)。或者,如果我们要熬了这一切的一句话:一个interface
就是实现类有,但一abstract
类是子类什么的。
为了给出一个简单而明确的答案,它有助于设置上下文:当您不想提供完整的实现时,可以同时使用两者。
然后,主要区别是接口根本没有实现(只有没有主体的方法),而抽象类也可以具有主体的成员和方法,即可以部分实现。
default
Java 8中的关键字,您也可以使用该关键字在接口中定义具体方法。
代表实际实现的抽象类和接口之间的差异。
接口:它是一个关键字,用于定义对象的模板或方案,并强制所有子类遵循相同的原型,就实现而言,所有子类均可以根据需要自由实现功能这是必需的。
我们应该使用接口的其他一些用例。
通过接口完成两个外部对象之间的通信(在我们的应用程序中为第三方集成)在此处接口充当合同。
抽象类:抽象,它是一个关键字,当我们在任何类之前使用此关键字时,它便成为抽象类。它主要用于我们需要定义模板以及对象的某些默认功能之后,所有子类,这样就消除了多余的代码,并消除了一些可以使用抽象类的用例,例如我们希望其他任何类都不能直接实例化该类的对象,只有派生类可以使用该功能。
抽象类的示例:
public abstract class DesireCar
{
//It is an abstract method that defines the prototype.
public abstract void Color();
// It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.
// and hence no need to define this in all the sub classes in this way it saves the code duplicasy
public void Wheel() {
Console.WriteLine("Car has four wheel");
}
}
**Here is the sub classes:**
public class DesireCar1 : DesireCar
{
public override void Color()
{
Console.WriteLine("This is a red color Desire car");
}
}
public class DesireCar2 : DesireCar
{
public override void Color()
{
Console.WriteLine("This is a red white Desire car");
}
}
接口示例:
public interface IShape
{
// Defines the prototype(template)
void Draw();
}
// All the sub classes follow the same template but implementation can be different.
public class Circle : IShape
{
public void Draw()
{
Console.WriteLine("This is a Circle");
}
}
public class Rectangle : IShape
{
public void Draw()
{
Console.WriteLine("This is a Rectangle");
}
}
您可以在接口和抽象类之间找到明显的区别。
接口
抽象类
抽象类包含抽象和非抽象方法。
继承抽象类时,不强制用户实现所有方法。
包含各种变量,包括原始变量和非原始变量
声明使用abstract关键字。
可以以任何可见性定义抽象类的方法和成员。
子类只能扩展一个类(抽象或具体)。
抽象类是无法创建对象的类或无法实例化的类。抽象方法使类抽象。为了继承在抽象类中声明的方法,需要继承一个抽象类。对访问说明符没有限制。抽象类中可以包含构造函数和其他具体(非abstarct方法)方法,但接口不能具有。
接口是方法的蓝图/模板(例如,给纸房子(接口房子),而不同的建筑师将使用他们的想法来构建它(实现房屋接口的建筑师类别)。抽象方法,默认方法,静态方法,最终变量和嵌套类。所有成员都将是final或public,protected和private访问指定符。不允许对象创建。实现接口并重写接口中声明的抽象方法接口是松耦合(动态多态/动态绑定)的一个很好的例子。接口实现多态和抽象。实现类。例如一家汽车公司,它希望所有制造的汽车的某些功能都相同,以便该公司将制造具有这些功能的接口汽车,而不同类别的汽车(例如Maruti Suzkhi,Maruti 800)将被覆盖这些功能。
我们已经有了抽象类时为什么要接口?Java仅支持多级继承和层次结构继承,但是借助接口,我们可以实现多重继承。
从实用性角度讲,抽象类和接口之间的主要区别是 抽象类可以保持状态。 除了保持状态,我们还可以使用Interface来实现rest操作。
在一个接口中,所有方法都必须仅是定义,而不能实现单个方法。
但是在抽象类中,必须有一个仅具有定义的抽象方法,但是其他方法也可以在具有实现的抽象类中...
接口和抽象类之间存在各种结构/语法上的差异。还有更多区别
[1] 基于方案的差异:
当我们希望限制用户创建父类的对象并且我们相信将来会添加更多的抽象方法时,可以使用抽象类。
当我们确定没有更多的抽象方法可以使用时,必须使用接口。然后仅发布一个接口。
[2] 概念差异:
如果是,则“将来是否需要提供更多抽象方法”,如果否,则将其设置为接口。
(最合适且有效直到java 1.7)