接口和抽象类之间到底有什么区别?
当前回答
抽象类与接口的主题主要是语义。
抽象类在不同的编程语言中通常充当接口的超集,除了一点,即可以实现多个接口,但只能继承一个类。
接口定义了某件事情必须能够做的事情;类似于合同,但不提供其实现。
抽象类定义了什么是什么,它通常托管子类之间的共享代码。
例如,格式化程序应该能够格式化()某些内容。描述这种情况的常见语义是创建一个接口IFormatter,该接口带有一个format()声明,其作用类似于一个契约。但是IFormatter并不描述什么是什么,而是描述它应该能够做什么。在本例中,我们创建一个抽象类。。。因此,我们创建了一个实现接口的抽象类Formatter。这是一个非常描述性的代码,因为我们现在知道我们有一个格式化程序,我们现在知道每个格式化程序必须能够做什么。
还有一个非常重要的主题是文档(至少对某些人来说…)。在您的文档中,您可能希望在子类中解释Formatter实际上是什么。有一个抽象类Formatter非常方便,您可以链接到子类中的文档。这是非常方便和通用的。另一方面,如果您没有抽象类Formatter,而只有接口IFormatter,则必须在每个子类中解释Formatter实际上是什么,因为接口是一个契约,你不会在接口的文档中描述Formatter实际上是什么-至少这不是常见的事情,你会打破大多数开发人员认为正确的语义。
注意:使抽象类实现接口是一种非常常见的模式。
其他回答
唯一的区别是一个可以参与多重继承,另一个不能。
接口的定义随着时间的推移而改变。你认为一个接口只有方法声明,只是契约吗?Java 8之后的静态最终变量和默认定义呢?
由于多重继承的菱形问题,接口被引入到Java中,而这正是它们真正想要做的。
接口是为解决多重继承问题而创建的构造,可以具有抽象方法、默认定义和静态最终变量。
请参阅为什么Java只允许在接口中使用静态最终变量,而这些变量仅用于契约?。
可以在此处找到解释:http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
抽象类是一个仅部分由程序员它可能包含一个或多个抽象方法。抽象方法只是一个函数定义用于告诉程序员方法必须在子级中实现班接口类似于抽象班实际上,接口占据了与类和抽象名称空间相同类。因此,您不能定义具有相同名称的接口作为一个班级。接口是一个完整的抽象类;没有一种方法实现,而不是类从中派生出来,据说实现该接口。
无论如何,我觉得这个接口的解释有些混乱。更常见的定义是:接口定义实现类必须履行的契约。接口定义由公共成员的签名组成,没有任何实现代码。
如果您有一些可供多个类使用的通用方法,请使用抽象类。否则,如果你想让类遵循某种明确的蓝图,就去寻找接口。
以下示例演示了这一点。
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。抽象类可以有非final变量。默认情况下,Java接口中声明的变量是静态的。抽象类可以具有非静态变量。默认情况下,Java接口的成员是公共的。Java抽象类可以具有类成员的通常风格,如private、protected等。。
您可以发现接口和抽象类之间的明显区别。
界面
接口仅包含抽象方法。强制用户在实现接口时实现所有方法。仅包含最终变量和静态变量。使用interface关键字声明。接口的所有方法都必须定义为public。一个接口可以扩展,或者一个类可以实现多个其他接口。
抽象类
抽象类包含抽象和非抽象方法。继承时不强制用户实现所有方法抽象类。包含所有类型的变量,包括基元和非基元使用abstract关键字声明。抽象类的方法和成员可以使用任何可见度子类只能扩展单个类(抽象或具体)。
简而言之,差异如下:
接口和抽象类之间的语法差异:
抽象类的方法和成员可以具有任何可见性。接口的所有方法都必须是公共的//Java 9不再适用抽象类的具体子类必须定义所有抽象方法。抽象子类可以具有抽象方法。扩展另一个接口的接口不需要为从父接口继承的方法提供默认实现。子类只能扩展单个类。一个接口可以扩展多个接口。一个类可以实现多个接口。子类可以定义具有相同或更少限制性可见性的抽象方法,而实现接口的类必须将所有接口方法定义为公共的。抽象类可以有构造函数,但不能有接口。来自Java9的接口具有私有静态方法。
现在在界面中:
公共静态-支持公共摘要-支持公共默认值-支持私有静态-支持私有抽象-编译错误私有默认值-编译错误私有-支持