使类抽象的主要优点是什么?

时间:2011-01-12 18:00:39

标签: java abstract-class

为什么我们将一个类声明为抽象?我知道它无法实例化,但为什么要给它一个特殊的关键字。即使是“普通”类也可以正常工作,并且可以轻松地进行子类化。那么使一个类抽象的主要优点是什么?

9 个答案:

答案 0 :(得分:6)

在抽象类中,您可以实现一些方法,并且可以使您的客户端也必须实现一些抽象。你可以提供一些常用的功能,也可以在这里有一些继承的字段和一些骨架方法

答案 1 :(得分:3)

我认为你误解了抽象类的重点:它们提供了一些功能的部分实现,但不是完整的实现。

您建议抽象类是多余的,因为您可以使用public void methodname(){}定义不完整的方法 - 这当然可以。但是,假设您的客户端继承自以这种方式定义的类,他们如何知道要覆盖哪些方法?如果他们忘记覆盖方法会发生什么?现在他们的派生类有一个不完整的定义 - 你不希望这样。

abstract关键字强制客户端为某些方法提供实现,否则代码甚至不会编译。换句话说,它提供了编译时保证,您使用或创建的类已完全实现。

答案 2 :(得分:2)

声明类abstract会阻止任何代码实例化该类。

这强制设计指南使非叶类抽象化。

它允许您稍后向您的超类(以及子类的实现)添加抽象方法,而不会影响任何现有客户端。

即使非叶类当前没有任何抽象方法,abstract关键字仍然有效。

答案 3 :(得分:2)

抽象类可以有抽象方法和“具体”方法。

“具体”方法可以使用抽象方法,并且可以确保它们在运行时被(正确)强制化。因为每个(非抽象)子类都必须实现它们。 (并且它不会是抽象类itselfe的实例)。

所以关于拯救! - 它确保想要子类化抽象类的程序员必须实现抽象方法。

如果只使用普通类执行此操作,那么对应于抽象类的类将具有带有空实现的(抽象)方法,并且只有程序员必须重写此方法。< / p>

当然,你可以将抽象类的概念用于其他思想,比如创建不可实现的类,但这不是主要观点。

答案 4 :(得分:2)

只是一个真实的例子。我有一个GUI抽象类,它是我所有GUI组件的父类。让我们称之为AbstractSuperClass。扩展AbstractSuperClass的每个组件都需要自己实现save函数。因此,制作我的超类抽象的好处是我可以拥有一个AbstractSuperClass类型的数组,它可以容纳我的所有GUI组件。然后我可以循环遍历该数组并调用save函数,知道每个GUI组件都有自己的save方法。由于该类是抽象的,它强制我的子类提供save函数的实现。

这特别有用,因为当我们向其他程序员开放API时,他们没有得到源代码。它们只是扩展AbstractSuperClass并且必须提供保存实现。

答案 5 :(得分:0)

如果您想拥有一组继承相同逻辑功能的类,这将非常有用。  但同时,该类仅实现基本逻辑,并且不包含任何实际功能。

您应该将其视为骨架类。

例如,我曾经制作了一个具有这些规范的课程:

  1. 控制在另一个线程上执行命令的过程,并转发该过程的事件。

  2. 该类本身没有任何功能(没有实现实际的work()函数)

  3. 所以结果是一个可以继承的抽象类,它已经有一个内置的线程控件,你需要做的只是实现work()方法。

答案 6 :(得分:0)

如果您的类有一些默认行为,并且您希望扩展类实现其他一些行为,那么您使用抽象类。它们无法初始化,您可以将抽象类视为扩展类的模板。

抽象类也可以调用抽象方法,在结果中调用扩展对象的方法。无论如何,有很多关于何时使用抽象类的讨论,何时在界面上更喜欢它。进行谷歌搜索,这是一个史诗般的讨论:)接口与抽象类。

答案 7 :(得分:0)

如果创建一个实例(你会创建子类的实例)几乎没有任何意义,你会将一个类声明为抽象。

public abstract class Shape {
    public double calculateArea();
}

public class Square : Shape {
    private double side;

    double calculateArea() {
        return side*side;
    }
}

public class Circle: Shape {
    private double radius;

    double calculateArea() {
        return 3.1415 * radius * radius;
    }
}

public class MainClass() {
    public static void Main() {
        Shape myShape = new Square();
        system.out.print(myShape.calculateArea());
        myShape = new Circle();
    }
}

创建Shape的实例是没有意义的,因为它并不意味着任何具体的东西,它是一个抽象的概念。但是,您可以使用Shape类型的变量,它允许您围绕公共基类型进行编程(尽管可以认为在这种情况下接口可能更好)。

答案 8 :(得分:0)

通常,如果存在继承,如在超级域类中,使用常见方法和子类中的常见实现,那么请考虑使用抽象类,这不是经常使用的,但我确实使用它。

如果你只是因为存在继承而使用抽象类,那么如果代码发生很大变化,你可能会遇到问题。这里的示例非常详细:Interfaces vs Abstract Classes in Java,用于电机的不同类型的域对象。其中一个需要双动力马达,而不是特定的单一类型,如太阳能或电池供电的马达。这需要两个运动类型的多个子类实现方法在单个子类中使用,这是抽象类可能变得混乱的地方。

总结一下,作为一项规则,您希望使用接口而不是Abstract类来定义行为(对象将执行的操作)。在我看来,Abstract类的主要优点是当用例的重点是实现层次结构和子类的代码重用时。