10

根据我的经验,我认为以下是正确的。如果我遗漏了一个要点,请告诉我。

界面:

接口中声明的每一个方法都必须在子类中实现。接口中只能存在事件、委托、属性 (C#) 和方法。一个类可以实现多个接口。

抽象类:

只有抽象方法必须由子类实现。抽象类可以具有带有实现的普通方法。除了事件、委托、属性和方法之外,抽象类还可以具有类变量。由于 C# 中不存在多重继承,一个类只能实现一个抽象类。

所以即使这种差异也不能解释问题

1)如果你有一个只有抽象方法的抽象类怎么办?这与界面有何不同?

2)如果你在接口中有一个公共变量,那与抽象类有什么不同呢?

所以任何解释都会有不同的帮助。

4

12 回答 12

4

除了技术差异之外,主要是您的设计意图导致您决定使用其中一种:

接口定义了实现它们的类的公共 API。您使用接口的目标应该是显示实现它的类的用法。一个类可以实现不同的接口以显示它可以扮演的不同角色,这不是副作用,而是一个中心设计目标。

抽象类应该实现一些基本算法常见行为。主要是将子类的通用功能加入到一个地方。它的目的是定义内部使用或流程,而不是公共接口。如果你想发布一个抽象类的使用,它应该实现一个单独的接口。

所以:

1) 当您使用上述指南时,只有公共抽象方法的抽象类没有任何意义。抽象类可以定义受保护的抽象方法来定义流程或算法。但这对于接口是不可能的。

2)除了公共属性抽象类可以定义受保护的实例变量,因此有更多的使用场景(见上面的解释)。

编辑:作者删除了“java”标签。我试图使它尽可能通用,它应该适用于 java 和 C#

于 2013-07-23T12:57:39.487 回答
3

在 Java 中:

一个abstract class可以implement一个interface

一个interface 不能 extend一个abstract class

顺便说一句:奇怪的是 - 一个abstract class罐头,实际上implementinterface没有这样做。

interface I {
  public String hello ();
}

interface J {
  public String goodbye ();
}

abstract class A implements I, J {
  @Override
  abstract public String hello ();
}

class B extends A {

  @Override
  public String hello() {
    return "Hello";
  }

  @Override
  public String goodbye() {
    return "goodbye";
  }

}
于 2013-07-23T12:54:42.290 回答
3

默认情况下,接口的所有变量都是公共的和静态的,接口中不能有唯一的公共变量,而在抽象类中可以声明公共变量。

如果一个类扩展了一个抽象类,那么它们之间就没有任何契约。扩展它的类可能会或可能不会覆盖抽象方法,但是在接口的情况下,接口和实现它的类之间有严格的约定,即该类必须覆盖该接口的所有方法。因此,从抽象方法的角度来看,它们看起来是相同的,但具有完全不同的特性和优势。

于 2013-07-23T12:55:51.430 回答
2

虽然您的问题表明它是针对“一般 OO”的,但它似乎确实专注于 .NET 对这些术语的使用。

  • 接口可以没有状态或实现
  • 实现接口的类必须提供该接口所有方法的实现
  • 抽象类可能包含状态(数据成员)和/或实现(方法)
  • 可以在不实现抽象方法的情况下继承抽象类(尽管这样的派生类是抽象的)
  • 接口可能是多重继承的,抽象类可能不是(这可能是接口与抽象类分开存在的关键具体原因——它们允许实现多重继承,从而消除了一般 MI 的许多问题)。

作为一般的 OO 术语,这些差异不一定是明确定义的。例如,有些 C++ 程序员可能持有类似的严格定义(接口是抽象类的严格子集,不能包含实现),而有些人可能会说具有某些默认实现的抽象类仍然是接口或非抽象类仍然可以定义一个接口。

事实上,有一个称为非虚拟接口 (NVI) 的 C++ 习惯用法,其中公共方法是非虚拟方法,它们“转换”到私有虚拟方法:

http://www.gotw.ca/publications/mill18.htm http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface

于 2013-07-23T12:47:56.017 回答
2

如果你有一个只有抽象方法的抽象类怎么办?这与界面有何不同?

  • 您可以实现多个接口,但只能扩展一个类
  • 抽象类比接口更不受更改的影响,因为如果您更改接口,它将破坏实现它的类。
  • 接口只能有static final字段。抽象类可以有任何类型的字段。
  • 接口没有构造函数但抽象类可以有

但是java docs这么说

如果抽象类仅包含抽象方法声明,则应将其声明为接口。

于 2013-07-23T12:50:14.920 回答
2

即使今天抽象类版本中的所有方法都是抽象的,该类的未来版本也可以添加虚拟或非虚拟方法,而无需强制修改实现或重新编译使用者。相比之下,向接口添加任何成员通常需要修改实现该接口的所有类以实现该成员,并且无论更改是否添加了尚未实现的任何内容,实现和消费者通常都必须重新编译。

可以在不破坏实现或消费者的情况下更改抽象更改这一事实是有利于抽象类的一大优势。另一方面,抽象类将强制任何实现类单独从它派生,而不是从其他类派生。相比之下,接口几乎会限制其实现者可以继承或派生的内容。这是有利于接口的一大优势。

因为抽象类和接口各有各的优势,所以有时两者都可能比另一个更好。从概念上讲,可以在接口的工作方式中添加一些特性,从而赋予它们目前只有抽象类才能享受的优势,但我知道没有具体计划这样做。

于 2013-12-09T17:44:14.980 回答
1

您的类只能扩展一个抽象类并实现许多接口。

于 2013-07-23T12:45:08.847 回答
1

好吧,在抽象类中,您也可以有字段,并且不需要重新实现自动属性。您还可以指定不是public. 此外,它具有更好的可扩展性(例如,您可以使用[Obsolete]标记旧实现,然后让新实现默认调用旧实现)。此外,它会阻止您拥有更多的类继承。另一件事是您可以在抽象类中设置静态字段。

此外,接口通常是执行动作的东西,而类就是这样

于 2013-07-23T12:46:12.460 回答
1
*1) What if you had an Abstract class with only abstract methods? How would that be different from an interface?*

默认情况下,接口中的方法是“公共抽象”,抽象类也将抽象方法作为“公共抽象”。如果抽象类只包含抽象方法,那么最好将其设为接口。

*2) What if you had a Public variable inside the interface, how would that be different than in Abstract Class?*

接口不能有变量。如果您的意思是属性、事件、委托等......默认情况下它们将是“公共的”。如果抽象类中没有指定任何内容,它将是“私有”(仅关于接口/抽象类的成员)。

于 2013-11-27T01:35:23.227 回答
0

当您希望您的类能够做某事时,使用接口。

当存在'is a'关系时,您的类扩展了一个抽象类。

存在语义差异。

于 2013-07-23T12:48:41.447 回答
0

在抽象类的情况下。

class Dog : abstractAnimal

当我们创建 Dog 的对象时,我们将不得不创建 abstractAnimal 的对象,这会导致额外的对象创建。

在接口的情况下。

class Dog : IAnimal

当我们创建 Dog 的对象时,我们不会创建任何额外的对象。

于 2017-04-03T02:08:24.563 回答
0

在这种情况下,您可以说:

1)我们可以为类中存在的方法指定不同的访问修饰符,但我们不能更改接口成员的访问修饰符。

2) 从抽象派生的类不会强制执行。

于 2018-01-14T17:51:26.210 回答