抽象方法和类

抽象类是声明为abstract的类,它可以包含也可以不包含抽象方法。抽象类不能被实例化,但是可以被子类化。

抽象方法是一种无需实现即可声明的方法(不带花括号,后跟分号),如下所示:

abstract void moveTo(double deltaX, double deltaY);

如果类包含抽象方法,则必须将类本身声明为abstract,如下所示:

public abstract class GraphicObject {
   // declare fields
   // declare nonabstract methods
   abstract void draw();
}

当抽象类被子类化时,该子类通常为其父类中的所有抽象方法提供实现。但是,如果没有,则子类也必须声明为abstract

Note:

interface中未声明为默认或静态的方法(请参见Interfaces部分)是隐式抽象的,因此abstract修饰符不适用于interface方法。 (可以使用,但不必要.)

抽象类与interface的比较

抽象类类似于interface。您无法实例化它们,它们可能包含使用或不使用实现声明的方法的混合。但是,使用抽象类,您可以声明非静态和final字段,并定义公共,受保护的和私有的具体方法。使用interface时,所有字段都自动是公共的,静态的和final的,并且您声明或定义的所有方法(作为默认方法)都是公共的。另外,无论是否抽象,您都只能扩展一个类,而您可以实现任何数量的interface。

您应该使用哪个抽象类或interface?

  • 如果以下任何一种情况适用于您的情况,请考虑使用抽象类:

  • 您想在几个紧密相关的类之间共享代码。

    • 您期望扩展您的抽象类的类具有许多公共方法或字段,或者需要除 public(例如 protected 和 private)之外的访问修饰符。

    • 您要声明非静态或非final字段。这使您能够定义可以访问和修改它们所属对象的状态的方法。

  • 如果以下任何一种情况适用于您的情况,请考虑使用interface:

  • 您期望不相关的类将实现您的interface。例如,interfaceComparableCloneable由许多不相关的类实现。

    • 您想指定特定数据类型的行为,但不关心谁实现了它的行为。

    • 您想利用类型的多重继承。

JDK 中的抽象类的一个示例是AbstractMap,它是 Collections Framework 的一部分。它的子类(包括HashMapTreeMapConcurrentHashMap)共享AbstractMap定义的许多方法(包括getputisEmptycontainsKeycontainsValue)。

JDK 中实现多个interface的类的示例是HashMap,该类实现了SerializableCloneableMap<K, V>interface。通过阅读此interface列表,您可以推断HashMap的实例(无论实现该类的开发人员或公司如何)都可以克隆,并且可以序列化(这意味着可以将其转换为字节流;请参见Serializable Objects部分)。 ),并具有 Map 功能。此外,Map<K, V>interface已通过许多默认方法进行了增强,例如mergeforEach,实现此interface的旧类无需定义。

注意,许多软件库同时使用抽象类和interface。 HashMap类实现了多个interface,并且还扩展了抽象类AbstractMap

抽象类示例

在面向对象的绘图应用程序中,您可以绘制圆形,矩形,直线,贝塞尔曲线和许多其他图形对象。这些对象都有共同的某些状态(例如:位置,方向,线条颜色,填充颜色)和行为(例如:moveTo,旋转,调整大小,绘制)。所有图形对象的某些状态和行为都是相同的(例如:position,fill color 和 moveTo)。其他的则需要不同的实现(例如,调整大小或绘制)。所有GraphicObject都必须能够自行绘制或调整大小;他们只是在做事方式上有所不同。对于抽象超类来说,这是一个完美的情况。您可以利用这些相似之处,并声明所有图形对象都将从同一抽象父对象(例如GraphicObject)继承,如下图所示。

从 RectectObject 继承的 Rectangle,Line,Bezier 和 Circle 类

从 RectectObject 继承的 Rectangle,Line,Bezier 和 Circle 类

首先,您声明一个抽象类GraphicObject,以提供所有子类(例如当前位置和moveTo方法)完全共享的成员变量和方法。 GraphicObject还声明了诸如drawresize之类的方法的抽象方法,这些方法必须由所有子类实现,但必须以不同的方式实现。 GraphicObject类可以如下所示:

abstract class GraphicObject {
    int x, y;
    ...
    void moveTo(int newX, int newY) {
        ...
    }
    abstract void draw();
    abstract void resize();
}

GraphicObject的每个非抽象子类(例如CircleRectangle)都必须提供drawresize方法的实现:

class Circle extends GraphicObject {
    void draw() {
        ...
    }
    void resize() {
        ...
    }
}
class Rectangle extends GraphicObject {
    void draw() {
        ...
    }
    void resize() {
        ...
    }
}

抽象类实现interface时

Interfaces的小节中,注意到实现interface的类必须实现interface的所有方法。但是,可以定义一个不实现所有interface方法的类,前提是该类被声明为abstract。例如,

abstract class X implements Y {
  // implements all but one method of Y
}

class XX extends X {
  // implements the remaining method in Y
}

在这种情况下,类X必须为abstract,因为它没有完全实现Y,但实际上XX类可以实现Y

Class Members

抽象类可能具有static个字段和static个方法。您可以将这些静态成员与类引用(例如AbstractClass.staticMethod())一起使用,就像对其他任何类一样。