界面和抽象类有什么区别?

eea 发布于 2019-11-10 interface 最后更新 2019-11-10 12:11 122 浏览

接口和抽象类的区别究竟是什么?

已邀请:

hquae

赞同来自:

内容太长未翻译

yeum

赞同来自:

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

enter image description here 取自: 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

xqui

赞同来自:

可在此处找到解释:http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm

An abstract class is a class that is only partially implemented by the programmer. It may contain one or more abstract methods. An abstract method is simply a function definition that serves to tell the programmer that the method must be implemented in a child class. An interface is similar to an abstract class; indeed interfaces occupy the same namespace as classes and abstract classes. For that reason, you cannot define an interface with the same name as a class. An interface is a fully abstract class; none of its methods are implemented and instead of a class sub-classing from it, it is said to implement that interface.
无论如何,我发现接口的这种解释有点令人困惑。更常见的定义是:接口定义实现类必须满足的合同。接口定义由公共成员的签名组成,没有任何实现代码。

paut

赞同来自:

总结起来的最简单方法是interface是:

  1. 完全抽象,除了defaultstatic方法之外;虽然它有defaultstatic方法的定义(方法签名+实现),但它只有其他方法的声明(方法签名)。
  2. 遵守比规则更宽松的规则(一个类可以实现多个interfaces,interface可以从多个interface继承)。无论是否指定为public static final,所有变量都是隐式常量。无论是否指定,所有成员都隐含地为public
  3. 通常用于保证实现类具有指定的功能和/或与实现相同接口的任何其他类兼容。
同时,abstract类是:
  1. 从完全抽象到完全实现的任何地方,倾向于拥有一个或多个abstract方法。可以包含声明和定义,声明标记为abstract
  2. 一个完整的类,并且遵守管理其他类的规则(只能从一个类继承),条件是它无法实例化(因为无法保证它已完全实现)。可以有非常量成员变量。可以实现成员访问控制,将成员限制为protectedprivate或私有包(未指定)。
  3. 通常用于提供尽可能多的子类共享的实现,或者提供程序员能够提供的尽可能多的实现。
或者,如果我们想把它全部归结为一个句子:interface就是实现类所具有的,但是abstract类就是子类。

nin

赞同来自:

enter image description here 这是对接口与抽象类的非常基本的理解。

jalias

赞同来自:

在接口中,所有方法必须只是定义,而不是单个应该实现。 但是在抽象类中必须有一个只有定义的抽象方法,但是其他方法也可以在抽象类中实现...

benim

赞同来自:

接口 一个接口是一个契约:编写界面的人说:“嘿,我接受看起来那样的东西”,使用界面的人说“好吧,我写的课看起来那样”。 接口是一个空壳。只有方法的签名,这意味着方法没有正文。界面无能为力。这只是一种模式。 例如(伪代码):
// 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模块获得的编程技巧,实际上是使用元类,因此也就是类。接口与这种语言中的duck typing更相关,它是约定和调用描述符的特殊方法( __method__ 方法)之间的混合。 与编程一样,有另一种语言的理论,实践和实践:-)

taut

赞同来自:

abstract classinterface之间的主要技术差异是:

  • 抽象类可以有常量,成员,方法存根(没有主体的方法)和定义的方法,而接口只能有常量和方法存根。
  • 可以使用任何可见性定义抽象类的方法和成员,而接口的所有方法都必须定义为public(默认情况下它们是公共的)。
  • 当继承抽象类时,具体子类必须定义抽象方法,而抽象类可以扩展另一个抽象类,而不必定义父类中的抽象方法。
  • 类似地,扩展另一个接口的接口不负责从父接口实现方法。这是因为接口无法定义任何实现。
  • 子类只能扩展单个类(抽象或具体),而接口可以扩展,或者类可以实现多个其他接口。
  • 子类可以定义具有相同或更少限制性可见性的抽象方法,而实现接口的类必须定义具有完全相同可见性的方法(公共)。

kaut

赞同来自:

没有任何实现的抽象类看起来像一个接口;但是,抽象类和接口之间存在许多差异而不是相似之处。让我们解释这两个概念并比较它们的相似点和不同点。 什么是抽象类? 抽象类是一种无法实例化的特殊类。所以问题是为什么我们需要一个无法实例化的类?抽象类只是被分类(继承自)。换句话说,它只允许其他类继承它但不能实例化。优点是它为所有子类强制执行某些层次结构。简单来说,它是一种强制所有子类进行相同层次结构或标准的契约。 什么是界面? 接口不是类。它是一个由Interface定义的实体。接口没有实现;它只有签名或换言之,只是没有正文的方法的定义。作为与Abstract类相似的一个,它是一个用于定义所有子类的层次结构的契约,或者它定义了特定的方法集及其参数。它们之间的主要区别在于类可以实现多个接口,但只能从一个抽象类继承。由于C#不支持多重继承,因此接口用于实现多重继承。 两者一起 当我们创建一个接口时,我们基本上创建了一组方法,没有任何必须被实现的类重写的实现。它的优点是它为类提供了一种方法,使其成为两个类的一部分:一个来自继承层次结构,另一个来自接口。 当我们创建一个抽象类时,我们创建一个可能有一个或多个已完成方法的基类,但至少有一个或多个方法未完成并声明为抽象。如果抽象类的所有方法都未完成,那么它与接口相同。抽象类的目的是为一组派生类如何工作提供基类定义,然后允许程序员填充派生类中的实现。


接口和抽象类之间存在一些相似之处和不同之处。 enter image description here

ksequi

赞同来自:

根据定义,接口不能具有任何方法的实现,并且无法初始化成员变量。 但是,抽象类可以实现方法并初始化成员变量。 当您期望合同发生变化时,请使用抽象类,即,将来您可能需要添加新方法。 在这种情况下,如果您决定使用接口,当接口更改为包含接口时,您的应用程序将在您转储新接口DLL时中断。 要详细阅读,请访问difference between abstract class and a interface

icum

赞同来自:

一些重要的差异: 以表格的形式:

Difference 作为stated by Joe from javapapers
1.Main difference is methods of a Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behavior. 2.Variables declared in a Java interface is by default final. An abstract class may contain non-final variables. 3.Members of a Java interface are public by default. A Java abstract class can have the usual flavors of class members like private, protected, etc.. 4.Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”. 5.An interface can extend another Java interface only, an abstract class can extend another Java class and implement multiple Java interfaces. 6.A Java class can implement multiple interfaces but it can extend only one abstract class. 7.Interface is absolutely abstract and cannot be instantiated; A Java abstract class also cannot be instantiated, but can be invoked if a main() exists. 8.In comparison with java abstract classes, java interfaces are slow as it requires extra indirection.

lnon

赞同来自:

不是原始问题的答案,但是一旦你得到它们之间的差异的答案,你将进入使用时 - 每个困境: When to use interfaces or abstract classes? When to use both? 我对OOP的知识有限,但是看到界面作为语法形容词的等价物直到现在都适用于我(如果这种方法是假的,请纠正我!)。例如,接口名称就像您可以为类提供的属性或功能,并且类可以包含许多类:ISerializable,ICountable,IList,ICacheable,IHappy,...

dquis

赞同来自:

如果要在继承层次结构中提供多态行为,请使用抽象类。 当您想要完全不相关的类的多态行为时,请使用接口。

qea

赞同来自:

如果您有一些可供多个类使用的常用方法,请转到抽象类。 否则,如果您希望类遵循一些明确的蓝图,请转到接口。 以下示例证明了这一点 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);
    }
}
简而言之,一些重要的关键点:
  1. Java界面中声明的变量默认为final。抽象类可以有非最终变量。
  2. Java接口中声明的变量默认为static。抽象类可以有非静态变量。
  3. 默认情况下,Java接口的成员是公共的。 Java抽象类可以具有通常的类成员类型,如private,protected等。

ueum

赞同来自:

实际上它非常简单。 您可以将接口视为一个类,只允许使用抽象方法而不允许其他方法。 因此,接口只能“声明”而不能定义您希望该类具有的行为。 抽象类允许您同时执行声明(使用抽象方法)以及定义(使用完整方法实现)您希望类具有的行为。 普通类只允许您定义,而不是声明您希望类具有的行为/操作。 最后一件事, 在Java中,您可以实现多个接口,但是您只能扩展一个(抽象类或类)... 这意味着定义行为的继承被限制为只允许每个类一个...即,如果你想要一个封装了A,B和C类行为的类,你需要执行以下操作:A类扩展B,C类扩展A ..它有点关于多重继承的方式... 另一方面,接口可以简单地做:接口C实现A,B 所以实际上Java只在“声明的行为”即接口中支持多重继承,并且只支持具有已定义行为的单继承..除非你按照我描述的方式进行循环... 希望这是有道理的。

gest

赞同来自:

唯一的区别是,一个人可以参与多重继承,而其他人则不能。 接口的定义随着时间的推移而发生了变化。你认为一个接口只有方法声明而且只是合同吗?那么静态最终变量以及Java 8之后的默认定义呢? 接口被引入Java,因为the diamond problem具有多重继承,这就是他们实际打算做的事情。 接口是为了避免多重继承问题而创建的构造,可以包含抽象方法,默认定义和静态最终变量。 请参阅Why does Java allow static final variables in interfaces when they are only intended to be contracts?

met

赞同来自:

我想补充一点其他有意义的差异。 例如,您有一个包含数千行代码的框架。现在,如果要使用方法enhanceUI()在整个代码中添加新功能,那么最好在抽象类中添加该方法,而不是在接口中添加。因为,如果在接口中添加此方法,则应在所有实现的类中实现它,但如果在抽象类中添加该方法则不是这种情况。

ut_quo

赞同来自:

抽象类和接口之间的差异代表真正的实现。 接口:它是一个关键字,用于定义对象的模板或蓝图,它强制所有子类都遵循相同的原型,对于实现,所有子类都可以自由地实现功能。这是要求。 我们应该使用接口的一些其他用例。 通过Interface here接口完成两个外部对象之间的通信(在我们的应用程序中进行第三方集成)作为Contract。 抽象类:抽象,它是一个关键字,当我们在任何类之前使用这个关键字然后它变成抽象类。它主要用于我们需要定义模板以及一个对象的一些默认功能,后面跟着所有子类和这种方式它删除了冗余代码和一个我们可以使用抽象类的用例,比如我们希望没有其他类可以直接实例化类的对象,只有派生类才能使用该功能。 抽象类的示例:

 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");
        }
    }

jquia

赞同来自:

重点是:

  • 摘要是面向对象的。它提供了“对象”应具有的基本数据和/或应该能够执行的功能。它关注对象的基本特征:它有什么以及它能做什么。因此,从同一抽象类继承的对象共享基本特征(泛化)。
  • 界面是面向功能的。它定义了对象应具有的功能。无论它是什么对象,只要它可以执行界面中定义的这些功能,就可以了。它忽略了其他一切。对象/类可以包含几个(组)功能;因此,一个类可以实现多个接口。

qanimi

赞同来自:

我正在建造一个300层的建筑 建筑的蓝图界面

  • 例如,Servlet(I)
建筑物最多可容纳200层 - 部分完工 - 抽象
  • 部分实现,例如,generic和HTTP servlet
建筑施工完成 - 混凝土
  • 完全实现,例如,自己的servlet
接口
  • 我们对实施,只是要求一无所知。我们可以 去寻找一个界面。
  • 默认情况下,每个方法都是公共的和抽象的
  • 这是一个100%纯粹的抽象类
  • 如果我们宣布公开,我们就不能申报私人和受保护的
  • 如果我们声明抽象,我们不能声明final,static,synchronized,strictfp和native
  • 每个界面都有公共,静态和最终
  • 序列化和瞬态不适用,因为我们无法在接口
  • 中创建实例
  • 非挥发性,因为它是最终的
  • 每个变量都是静态的
  • 当我们在接口内声明变量时,我们需要在声明
  • 时初始化变量
  • 不允许实例和静态阻止
抽象
  • 部分实施
  • 它有一个抽象的方法。另外,它使用具体的
  • 对抽象类方法修饰符没有限制
  • 对抽象类变量修饰符没有限制
  • 我们不能声明除抽象
  • 之外的其他修饰符
  • 初始化变量没有限制
  • 不允许使用构造函数
取自DurgaJobs网站

eos_et

赞同来自:

我不想强调差异,这些差异已在许多答案中说过(关于接口中变量的公共静态最终修饰符,以及对抽象类中受保护的私有方法的支持) 简单来说,我想说: interface:通过多个不相关的对象实现合同 抽象类:在多个相关对象之间实现相同或不同的行为 来自Oracle documentation 考虑使用抽象类,如果:

  1. 您希望在几个密切相关的类之间共享代码。
  2. 您希望扩展抽象类的类具有许多常用方法或字段,或者需要除公共之外的访问修饰符(例如protected和private)。
  3. 您想要声明非静态或非最终字段。
考虑使用接口:
  1. 您希望不相关的类能够实现您的界面。例如,许多不相关的对象可以实现Serializable接口。
  2. 您希望指定特定数据类型的行为,但不关心谁实现其行为。
  3. 您希望利用类型的多重继承。
抽象类与具体类建立“是一种”关系。 interface为类提供“具有”功能。 如果您正在寻找Java作为编程语言,这里还有一些更新: Java 8通过提供default方法功能在一定程度上缩小了interfaceabstract类之间的差距。接口没有方法的实现现在不再有效。 有关更多详细信息,请参阅此文档page。 看看这个SE问题,以便更好地理解代码示例。 How should I have explained the difference between an Interface and an Abstract class?

gnihil

赞同来自:

抽象类是无法创建其对象的类或无法实例化的类。 抽象方法使类抽象。 需要继承抽象类以覆盖抽象类中声明的方法。 访问说明符没有限制。 抽象类可以有构造函数和其他具体(非abstarct方法)方法,但接口不能有。 界面是方法的蓝图/模板。(例如,纸上的房子被给出(界面房屋),不同的建筑师将使用他们的想法来构建它(实现房屋界面的建筑师类)。 它是抽象方法,默认方法,静态方法,最终变量和嵌套类的集合。 所有成员都将是最终成员或公共成员,不允许使用受保护和私有访问说明符。不允许创建对象。 必须创建一个类才能使用实现接口,并且还要覆盖接口中声明的抽象方法。接口是松耦合的一个很好的例子(动态多态/动态绑定) 接口实现了多态性和抽象。它告诉我们该做什么但是如何做是由实现类定义的。 对于Eg。有一个汽车公司,它希望这样一些功能是相同的所有它是制造所以,该公司将形成交界面的车辆将有那些特点和不同类别的汽车(如马鲁蒂Suzkhi,马鲁蒂800)的车会覆盖这些功能(功能)。 为什么我们已经有抽象类的接口? Java仅支持多级和层级继承,但在接口的帮助下,我们可以实现多重继承。

killo

赞同来自:

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

Abstract Class
  • 对于抽象类,必须将方法声明为抽象。摘要 方法没有实现。
  • 可以使用像public这样的Access修饰符声明Abstract方法, 在子类中实现这些方法时,必须使用相同(或限制较少)的可见性来定义它们。
  • 抽象类可以包含变量和具体方法。
  • 一个类只能继承一个Abstract类
  • Abstract类无法进行多重继承。
Interface
  • 对于接口,默认情况下所有方法都是抽象的。 因此,无法在接口中声明变量或具体方法。
  • 接口中声明的所有方法都必须是公共的。
  • 接口不能包含变量和具体方法 常数。
  • 一个类可以实现许多接口
  • 可以进行多接口继承。

uet

赞同来自:

界面:转动(向左转,向右转。) 抽象类:轮子。 类别:方向盘,源自轮子,暴露界面转向 一个用于对可以在各种事物中提供的行为进行分类,另一个用于对事物的本体建模。

yut

赞同来自:

简而言之,差异如下: 接口和抽象类之间的语法差异:

  1. 抽象类的方法和成员可以具有任何可见性。接口的所有方法都必须是公共的。 //不再适用于Java 9
  2. Abstract Class的具体子类必须定义所有抽象方法。 Abstract子类可以有抽象方法。扩展另一个接口的接口不需要为从父接口继承的方法提供默认实现。
  3. 子类只能扩展一个类。接口可以扩展多个接口。一个类可以实现多个接口。
  4. 子类可以定义具有相同或更少限制性可见性的抽象方法,而实现接口的类必须将所有接口方法定义为public。
  5. 抽象类可以有构造函数,但不能有接口。
  6. Java 9的接口具有私有静态方法。
现在在Interfaces中: public static - 支持的
public abstract - 支持的
public default - 支持的
private static - 支持的
private abstract - 编译错误
private default - 编译错误
private - 支持

esaepe

赞同来自:

您可以在界面和抽象类之间找到明显的区别。 接口

  • 界面只包含抽象方法。
  • 强制用户在实现接口时实现所有方法。
  • 仅包含最终和静态变量。
  • 使用interface keyword声明。
  • 接口的所有方法都必须定义为public。
  • 接口可以扩展,或者类可以实现多个其他接口 接口。
抽象类
  • 抽象类包含抽象和非抽象方法。
  • 在继承时不强制用户实现所有方法 抽象类。
  • 包含各种变量,包括原始和非原始
  • 使用abstract keyword声明。
  • 抽象类的方法和成员可以用any定义 可视性。
  • 子类只能扩展一个类(抽象或具体)。

dmodi

赞同来自:

让我们再次讨论这个问题: 让你知道的第一件事是1/1和1 * 1会产生相同的结果,但这并不意味着乘法和除法是相同的。显然,他们保持着良好的关系,但请注意,两者都是不同的。 我将指出主要的不同之处,其余的已经解释过了: 抽象类对于类层次结构的建模很有用。乍一看任何要求,我们都清楚地知道要构建什么,但我们知道要构建什么。所以你的抽象类是你的基类。 接口对于让其他层次结构或类知道我能够做什么很有用。当你说我有能力时,你必须具备这种能力。接口将标记为类必须实现相同的功能。

iaut

赞同来自:

可以在Interface VS Abstract Class in PHP中找到解释。

结论 抽象类用于共享函数。接口用于分享您必须执行的操作。

bea

赞同来自:

继承用于两个目的:

  • 允许对象将父类型数据成员和方法实现视为自己的。
  • 允许对需要引用超类型对象的代码使用一种类型的对象的引用。
在支持广义多重继承的语言/框架中,通常很少需要将类型分类为“接口”或“抽象类”。然而,流行的语言和框架将允许类型将其他类型的数据成员或方法实现视为其自身,即使它们允许类型可替代任意数量的其他类型。 抽象类可能具有数据成员和方法实现,但只能由不从任何其他类继承的类继承。接口对实现它们的类型几乎没有限制,但不能包含任何数据成员或方法实现。 有时,类型可以替代许多不同的东西;还有一些时候,对象将父类型数据成员和方法实现视为自己的有用。区分接口和抽象类允许在最相关的情况下使用这些能力。

uautem

赞同来自:

关键点:

  • 抽象类可以有属性,数据字段,方法(完整/ 两个都不完整。
  • 如果方法或属性在abstract关键字中定义,必须在派生类中重写。(它的工作方式是紧密耦合 功能)
  • 如果为抽象类中的方法或属性定义abstract关键字,则无法定义方法体和获取/设置值 属性和必须在派生类中重写。
  • 抽象类不支持多重继承。
  • 抽象类包含构造函数。
  • 抽象类可以包含subs,functions,properties的访问修饰符。
  • 只有抽象类的完整成员可以是静态。
  • 接口只能从另一个接口继承,不能从抽象类继承,抽象类可以从另一个抽象类或其他接口继承。
优点:
  • 这是一种强制所有子类进行相同层次结构或标准的契约。
  • 如果各种实现属于同一种类并使用常见的行为或状态,则最好使用抽象类。
  • 如果我们向抽象类添加一个新方法,那么我们可以选择提供默认实现,因此所有现有代码都可以正常工作。
  • 允许快速执行而不是接口。(接口需要更多时间在相应的类中查找实际方法。)
  • 它可以用于紧密松散的耦合。
在这里找到细节...... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/

nautem

赞同来自:

为了给出一个简单但明确的答案,有助于设置上下文:当您不想提供完整实现时,可以使用两者。 那么主要的区别是接口根本没有实现(只有没有主体的方法),而抽象类也可以有成员和方法,也可以部分实现。

csequi

赞同来自:

接口与抽象类的比较是错误的。应该有另外两个比较:1)接口与类和2)抽象与最终类。

接口与类 接口是两个对象之间的契约。例如,我是邮递员,你是一个提供的套餐。我希望你知道你的送货地址。当有人给我一个包裹时,它必须知道它的送货地址:
interface Package {
  String address();
}
类是一组遵守合同的对象。例如,我是“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
  }
}

摘要与最终 抽象类是一组不完整的对象。他们不能使用,因为他们错过了一些部分。例如,我是一个抽象的GPS感知框 - 我知道如何检查我在地图上的位置:
abstract class GpsBox implements Package {
  @Override
  public abstract String address();
  protected Coordinates whereAmI() {
    // connect to GPS and return my current position
  }
}
如果由另一个类继承/扩展,该类可能非常有用。但它本身 - 它没用,因为它不能有物体。抽象类可以构建最终类的元素。 最终类是一组完整的对象,可以使用,但不能修改。他们确切知道如何工作和做什么。例如,我是一个总是进入其构造期间指定地址的Box:
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++,可能只有一个类,既不是抽象的也不是最终的。这样的类可以继承并可以实例化。但我并不认为这严格符合面向对象的范式。 同样,将接口与抽象类进行比较是不正确的。

uanimi

赞同来自:

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

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
}
现在,当一个人不需要那个类的实例,具有类似的逻辑,需要合同时,应该使用abstract。