接口和抽象类之间到底有什么区别?


当前回答

接口通常是没有逻辑的类,只有签名。而抽象类是具有逻辑的类。两者都支持作为接口的契约,所有方法都应该在子类中实现,但在抽象中只应该实现抽象方法。何时使用接口,何时抽象?为什么使用界面?

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

}

现在,当一个人不需要那个类的实例,具有类似的逻辑,需要契约时,应该使用抽象。

其他回答

接口与抽象类的比较是错误的。应该有另外两个比较: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类是一组完整的对象,可以使用,但不能修改。他们确切地知道如何工作和做什么。例如,我是一个盒子,它总是在构建过程中到达指定的地址:

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++,可能只有一个类,既不是抽象类也不是最终类。这样的类可以继承并实例化。不过,我认为这并不严格符合面向对象的范例。

同样,将接口与抽象类进行比较是不正确的。

接口只包含功能的定义/签名,如果我们有一些公共功能和公共签名,那么我们需要使用抽象类。通过使用抽象类,我们可以同时提供行为和功能。另一个继承抽象类的开发人员可以很容易地使用这个功能,因为他们只需要填写空白。

摘自:

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.htmlhttp://www.dotnetbull.com/2011/11/what-is-interface-in-c-net.html

简而言之,差异如下:

接口和抽象类之间的语法差异:

抽象类的方法和成员可以具有任何可见性。接口的所有方法都必须是公共的//Java 9不再适用抽象类的具体子类必须定义所有抽象方法。抽象子类可以具有抽象方法。扩展另一个接口的接口不需要为从父接口继承的方法提供默认实现。子类只能扩展单个类。一个接口可以扩展多个接口。一个类可以实现多个接口。子类可以定义具有相同或更少限制性可见性的抽象方法,而实现接口的类必须将所有接口方法定义为公共的。抽象类可以有构造函数,但不能有接口。来自Java9的接口具有私有静态方法。

现在在界面中:

公共静态-支持公共摘要-支持公共默认值-支持私有静态-支持私有抽象-编译错误私有默认值-编译错误私有-支持

抽象类和接口的一般思想是由使用这些通用“设置”(某种模板)的其他类(不能单独构建)来扩展/实现,这使得为以后扩展它的所有对象设置特定的通用行为变得简单。

抽象类具有常规方法集和抽象方法。扩展类在被抽象类扩展后可以包括未设置的方法。当设置抽象方法时,它们由稍后扩展抽象方法的类定义。

接口与抽象类具有相同的财产,但只包含抽象方法,这些方法可以在其他类中实现(可以是多个要实现的接口),这就创建了一个更持久的方法/静态变量定义。与抽象类不同,您不能添加自定义的“常规”方法。

为了给出一个简单但明确的答案,设置上下文是有帮助的:当您不想提供完整的实现时,可以同时使用这两种方法。

因此,主要的区别是接口根本没有实现(只有没有主体的方法),而抽象类也可以有具有主体的成员和方法,即可以部分实现。