【问题标题】:When to use abstract class or interface? [closed]何时使用抽象类或接口? [关闭]
【发布时间】:2010-11-16 07:55:19
【问题描述】:

为什么要创建抽象类或接口类,或者我们什么时候应该使用抽象类或接口类?

【问题讨论】:

标签: java interface abstract-class


【解决方案1】:

当您只想声明类必须具有哪些方法和成员时,使用接口。任何实现该接口的人都必须声明并实现该接口列出的方法。

如果您还想拥有默认实现,请使用抽象类。任何扩展抽象类的类都必须只实现它的抽象方法和成员,并且将具有抽象类的其他方法的一些默认实现,您可以覆盖或不覆盖。

--EDIT - 忘了提,Earwicker 提醒了我

最后,您可以实现任意数量的接口,但只能扩展一个类(无论是否抽象)。选择前请记住这一点。

【讨论】:

  • 这不是根本区别——你可以创建一个只有抽象方法的抽象类。
  • 这种情况下,为什么不用接口呢?
  • 语言不是我设计的! :) 理论上,您可以在抽象类中拥有一些受保护的数据字段,而这是您无法通过接口实现的。
  • 所以,它就像一个实现的成员;)
【解决方案2】:

关键区别在于您可以在一个类中implement 多个接口,但只能extend 一个抽象类。这是因为抽象类也可以定义存储数据的字段,而接口则不能。

【讨论】:

  • 好点!我不记得了。 Java(如 C#)不允许类的多重继承,但允许实现任意数量的接口。
  • 实际上你也可以在界面中拥有字段,但前提是它们是静态的和最终的
【解决方案3】:

抽象类是一个类,它至少有一个抽象方法,或者您也可以将所有方法设为抽象。显然它不能被实例化。您必须从一个抽象类继承并在继承类(即扩展抽象类的类)中实现抽象方法。

接口根本不是类(所以不要称它们为接口类)。接口定义了没有任何实现的方法的签名。接口也没有成员字段。如果在类中实现接口,则必须为接口提供的所有方法提供实现。

为一些可以有完全不同实现的东西定义一个通用的 API 是有意义的。抽象类对于那些基本相同但有一些细微差别的类更有用。您可以结合使用这两种方法。

Java 类库的collections framework 就是一个很好的例子。你有接口 List,它定义了 List 的行为方式。一些实现例如 ArrayList 和 LinkedList。由于它们的行为相似,因此对两者都起作用的东西是在抽象类 AbstactList 中实现的,它们都继承了这个。

【讨论】:

    【解决方案4】:

    请参阅接口基本上是一个“合同”。当你定义一个接口时,你就是在定义一个契约。在扩展抽象类的地方,实现接口。

    让我们考虑一个例子。

    public interface Friend {
    void hello();
    }
    

    现在您已经定义了一个约定,它规定任何想要实现Friend 的类都需要为方法hello() 提供定义。

    这是一个实现:

    public class myFriend implements Friend {
    public void hello()
    println("Done");
    }
    

    现在myFriend已经履行了合同。现在的问题是:接口应该用在哪里?

    接口可帮助您定义必须实现的行为。假设您有一个 A 类,它定义了一些功能。您希望其他类仅在定义特定行为(方法)时才使用此类功能。您在接口方面强制执行此限制。

    【讨论】:

      【解决方案5】:

      SamuelCarrijo似乎已经很好地回答了这个问题。

      除了 Java 之外,一些框架还需要一个接口才能使用。我正在考虑(比如说)dynamic proxies,或者一些客户端/服务器代理框架。这是因为他们使用对对象的自省来确定由对象实现的接口实现的方法。所以有时你必须为一个对象实现一个接口,而你通常不会打扰。

      注意这个接口的原因是Java特有的。

      【讨论】:

        【解决方案6】:

        在构建继承层次结构时使用抽象类。然而,大多数继承层次不应该太“深”(即太多的继承层次)。许多面向对象的设计书籍会偏爱接口而不是继承(我曾经读过的一本书引用了一位开发人员的话说“继承是你不会实现的最酷的[面向对象]功能”),因为这允许为类分配行为“ by contract”,其中合约为接口。

        值得注意的是 samuelcarrijo 的回答 - 如果您想要一个方法的默认实现,则必须使用一个具有该方法的具体实现的抽象类来为其提供默认实现。这个默认实现可以在子类中被覆盖。

        希望这会有所帮助!

        【讨论】:

          猜你喜欢
          • 2023-04-03
          • 2017-11-15
          • 2015-06-27
          • 2010-11-16
          • 1970-01-01
          • 1970-01-01
          • 2020-08-01
          • 2021-12-11
          • 2012-11-06
          相关资源
          最近更新 更多