接口和抽象类之间到底有什么区别?
当前回答
抽象类和接口的一般思想是由使用这些通用“设置”(某种模板)的其他类(不能单独构建)来扩展/实现,这使得为以后扩展它的所有对象设置特定的通用行为变得简单。
抽象类具有常规方法集和抽象方法。扩展类在被抽象类扩展后可以包括未设置的方法。当设置抽象方法时,它们由稍后扩展抽象方法的类定义。
接口与抽象类具有相同的财产,但只包含抽象方法,这些方法可以在其他类中实现(可以是多个要实现的接口),这就创建了一个更持久的方法/静态变量定义。与抽象类不同,您不能添加自定义的“常规”方法。
其他回答
您可以发现接口和抽象类之间的明显区别。
界面
接口仅包含抽象方法。强制用户在实现接口时实现所有方法。仅包含最终变量和静态变量。使用interface关键字声明。接口的所有方法都必须定义为public。一个接口可以扩展,或者一个类可以实现多个其他接口。
抽象类
抽象类包含抽象和非抽象方法。继承时不强制用户实现所有方法抽象类。包含所有类型的变量,包括基元和非基元使用abstract关键字声明。抽象类的方法和成员可以使用任何可见度子类只能扩展单个类(抽象或具体)。
我不想强调这些差异,这已经在很多答案中说过了(关于接口中变量的公共静态最终修饰符以及抽象类中受保护的私有方法的支持)
简单地说,我想说:
接口:通过多个不相关的对象实现合同
抽象类:在多个相关对象之间实现相同或不同的行为
来自Oracle文档
如果出现以下情况,请考虑使用抽象类:
您希望在几个密切相关的类之间共享代码。您希望扩展抽象类的类具有许多公共方法或字段,或者需要公共以外的访问修饰符(如protected和private)。您要声明非静态或非final字段。
如果出现以下情况,请考虑使用接口:
您希望不相关的类实现您的接口。例如,许多不相关的对象可以实现Serializable接口。您希望指定特定数据类型的行为,但不关心谁实现了它的行为。您希望利用类型的多重继承。
抽象类与具体类建立“是”关系。接口为类提供了“具有”功能。
如果您正在寻找Java作为编程语言,这里还有一些更新:
Java8通过提供默认方法特性,在一定程度上缩小了接口类和抽象类之间的差距。接口没有实现。方法现在不再有效。
有关详细信息,请参阅本文档页。
看看这个SE问题,了解代码示例,以便更好地理解。
我应该如何解释接口和抽象类之间的区别?
通常抽象类用于某些东西的核心,但接口用于附加外围设备。
当您想为车辆创建基本类型时,应该使用抽象类,但如果您想添加一些不属于车辆基本概念的功能或属性,则应该使用接口,例如,您想添加“ToJSON()”函数。
接口具有广泛的抽象范围,而不是抽象类。您可以在传递的论证中看到这一点。请查看以下示例:
如果您使用vehicle作为参数,您可以使用它的派生类型之一(公共汽车或汽车同一类别只是车辆类别)。但当您使用IMoveable接口作为参数时,您有更多的选择。
接口通常是没有逻辑的类,只有签名。而抽象类是具有逻辑的类。两者都支持作为接口的契约,所有方法都应该在子类中实现,但在抽象中只应该实现抽象方法。何时使用接口,何时抽象?为什么使用界面?
class Circle {
protected $radius;
public function __construct($radius)
{
$this->radius = $radius
}
public function area()
{
return 3.14159 * pow(2,$this->radius); // simply pie.r2 (square);
}
}
//Our area calculator class would look like
class Areacalculator {
$protected $circle;
public function __construct(Circle $circle)
{
$this->circle = $circle;
}
public function areaCalculate()
{
return $circle->area(); //returns the circle area now
}
}
我们只需要
$areacalculator = new Areacalculator(new Circle(7));
几天后,我们将需要矩形、正方形、四边形等区域。如果是这样,我们是否必须每次更改代码并检查实例是正方形、圆形还是矩形?现在OCP所说的是接口代码而不是实现。解决方案是:
Interface Shape {
public function area(); //Defining contract for the classes
}
Class Square implements Shape {
$protected length;
public function __construct($length) {
//settter for length like we did on circle class
}
public function area()
{
//return l square for area of square
}
Class Rectangle implements Shape {
$protected length;
$protected breath;
public function __construct($length,$breath) {
//settter for length, breath like we did on circle,square class
}
public function area()
{
//return l*b for area of rectangle
}
}
现在是面积计算器
class Areacalculator {
$protected $shape;
public function __construct(Shape $shape)
{
$this->shape = $shape;
}
public function areaCalculate()
{
return $shape->area(); //returns the circle area now
}
}
$areacalculator = new Areacalculator(new Square(1));
$areacalculator->areaCalculate();
$areacalculator = new Areacalculator(new Rectangle(1,2));
$areacalculator->;areaCalculate();
这不是更灵活吗?如果我们在没有接口的情况下进行编码,我们将检查每个形状冗余代码的实例。
现在什么时候使用抽象?
Abstract Animal {
public function breathe(){
//all animals breathe inhaling o2 and exhaling co2
}
public function hungry() {
//every animals do feel hungry
}
abstract function communicate();
// different communication style some bark, some meow, human talks etc
}
现在,当一个人不需要那个类的实例,具有类似的逻辑,需要契约时,应该使用抽象。
界面:转弯(左转,右转)
抽象类:轮子。
类别:方向盘,衍生自方向盘,暴露接口转向
一个是对可以在各种各样的事物中提供的行为进行分类,另一个是为事物本体建模。