何时何地使用抽象类以及何时何地在Java中使用接口?

时间:2011-11-04 23:24:25

标签: java interface abstract-class

抽象类和接口在Java中起着非常重要的作用,它们在某些情况下具有自己的重要性。它们具有某些特殊的特征。它们之间存在一些可观察到的差异。让我来介绍其中的一些。


接口和抽象类之间的主要区别之一是抽象类永远不能实例化,但接口却可以。

它们中的任何一个都不能被明确地声明为final,因为它们将被其他一些非抽象类继承。

它们都不能有静态方法。既不具体也不抽象(抽象静态方法确实存在,实际上根本不存在)。

接口永远不会有具体的方法(使用它的实际实现的方法),但抽象类也可以有具体的方法。

接口不能有构造函数,但是抽象类可以有。


这里可能会出现两个明显的问题。

抽象类永远不能被实例化,因为它本质上不是完全实现的类,并且它的完整实现要求它被其他一些非抽象类继承。如果是这样的话,抽象类不应该有它自己的构造函数,因为构造函数隐式返回它自己的类的对象而抽象类本身不能被实例化,因此它不应该有一个构造函数它是自己的。

界面看起来比抽象类看起来更好,更适合使用,因为它比抽象类强加的限制更少。在非常具体的情况中,界面是有用的,并且非常具体的情况,抽象类是否合适?希望!粗体字母将被考虑在内。

2 个答案:

答案 0 :(得分:2)

首先,你在一些地方确实是错的:

  • 接口和抽象类之间的主要区别之一是抽象类永远不能实例化,但接口却可以。

错误。抽象和接口都可以匿名实例化。

  • 他们两个都不能被宣布为最终版本,因为它们将由其他一些非抽象类继承。

没错,虽然我个人认为没有理由为什么界面不能成为最终版本所以无法扩展,但那只是我。我明白为什么他们做出了他们的决定。

  • 他们两个都不能拥有静态方法。既不具体也不抽象(抽象静态方法确实存在,实际上根本不存在)。

抽象类可以有静态方法;遗憾!

  • 一个接口永远不会有具体的方法(一个方法与它的实际实现),一个抽象类,但也可以有具体的方法。

是的,这是他们之间的主要区别之一。

  • 接口不能有构造函数,但是抽象类可以有。

是的,那是真的。

现在,让我们继续你的问题:

你的第一段没有问题。那里的问题是什么?如果是“如果你不能实例化它们,为什么允许抽象类有构造函数?”答案是儿童类可以使用它。这是一个例子

abstract class Parent {
    String name;
    int id;
    public Parent(String n, int i) { name = n; id = i; }
}

class Child extends Parent {
    float foo;
    public Child(String n, int i, float f) {
        super(n,i);
        foo = f;
    }
}

// later
Parent p = new Parent("bob",12); // error
Child c = new Child("bob",12); // fine!

您的第二段有问题,但格式不正确。我想你只是错过了一个'是'...... :)答案如下:

如果要定义合约,请使用界面。这是一个非常具体的例子:

public interface Set<E> {
    int size(); // determine size of the set
    boolean isEmpty(); // determine if the set is empty or not
    void add(E data); // add to the set
    boolean remove(E data); // remove from the set
    boolean contains(E data); // determine if set holds something
}

所有集合的四种常用方法。

如果要定义某些行为,但仍具有合同

,则使用抽象类
public abstract class AbstractSet<E> implements Set<E> {
   // we define the implementation for isEmpty by saying it means
   // size is 0
   public boolean isEmpty() { return this.size() == 0; }
   // let all the other methods be determined by the implementer
}

答案 1 :(得分:0)

大多数情况下,在决定是否应该使用接口或抽象类之间进行讨论时,它最终会定义如何使用它们,但不总是为什么以及何时使用?此外,您可能最终使用的其他明显的其他具体类和实用程序类也不会被提起。实际上,在我的想法中,回答问题的正确方法是确定您正在处理的关于域或实体对象的上下文,即您的用例是什么?

从很高的层面来说,Java由可以使用方法相互通信的对象(可以在现实世界中建模对象的实体或域对象)组成。无论如何,您希望使用接口对行为进行建模,并在继承时使用抽象类。

根据我的个人经验,我使用自上而下,然后自下而上的方法。我通过查看用例并查看我将需要的类来开始寻找继承。然后我看看是否有superClassOrInterfaceType(因为类和接口都定义了类型,为了简单起见,我将它们组合成一个单词。希望它不会使它更加混乱)包含的域对象所有对象,如在车辆的superClassOrInterfaceType中,如果我正在处理处理subtypeClassOrInterfaceTypes的用例,例如:汽车,卡车,吉普车和摩托车。如果存在层次关系,那么我定义了superClassOrInterfaceType和subtypeClassOrInterfaceTypes。

正如我所说,我通常首先要做的是为我正在处理的对象寻找一个公共域superClassOrInterfaceType。如果是这样,我寻找subtypeClassOrInterfaceTypes之间的常见方法操作。如果没有,我会查看是否存在常见的方法实现,因为即使您可能具有superClassOrInterfaceType并且可能具有常用方法,但实现可能不支持代码重用。在这一点上,如果我有共同的方法,但没有常见的实现,我倾向于接口。但是,通过这个简单的示例,我应该有一些常见的方法,在车辆subtypeClassOrInterfaceTypes之间可以重用代码的一些常见实现。

另一方面,如果没有继承结构,那么我从下往上开始查看是否有常用方法。如果没有通用的方法,也没有常见的实现,那么我选择一个具体的类。

通常,如果存在使用常见方法和常见实现的继承以及在同一子类型中需要多个子类型实现方法,那么我使用抽象类,这很少见,但我确实使用它。如果你只是因为存在继承而使用抽象类,那么如果代码发生很大变化,你可能会遇到问题。这里的示例非常详细:Interfaces vs Abstract Classes in Java,用于电机的不同类型的域对象。其中一个需要双动力马达,需要在单个子类型中使用多个子类型实现方法。

总结一下,作为一项规则,您希望使用接口而不是Abstract类来定义行为(对象将执行的操作)。抽象类专注于实现层次结构和代码重用。

以下是一些链接,详细介绍了这一点。

Thanks Type & Gentle Class

The Magic behind Subtype Polymorphism

Maximize Flexibility with Interfaces & Abstract Classes

Interfaces vs Abstract Classes in Java