Documentation

The Java™ Tutorials
Hide TOC
Abstract Methods and Classes抽象方法和抽象类
Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance

Abstract Methods and Classes抽象方法和类

An abstract class is a class that is declared abstract—it may or may not include abstract methods. 抽象类是声明为abstract的类—它可能包括也可能不包括抽象方法。Abstract classes cannot be instantiated, but they can be subclassed.抽象类不能实例化,但可以子类化。

An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this:抽象方法是在没有实现的情况下声明的方法(不带大括号,后跟分号),如下所示:

abstract void moveTo(double deltaX, double deltaY);

If a class includes abstract methods, then the class itself must be declared abstract, as in:如果类包含抽象方法,则必须将该类本身声明为abstract,如中所示:

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

When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. 当抽象类被子类化时,子类通常为其父类中的所有抽象方法提供实现。However, if it does not, then the subclass must also be declared abstract.但是,如果没有,那么子类也必须声明为abstract


Note: Methods in an interface (see the Interfaces section) that are not declared as default or static are implicitly abstract, so the abstract modifier is not used with interface methods. 接口中未声明为默认方法或静态方法的方法(请参见接口部分)是隐式抽象的,因此抽象修饰符不与接口方法一起使用。(It can be used, but it is unnecessary.)(可以使用,但不需要。)

Abstract Classes Compared to Interfaces抽象类与接口的比较

Abstract classes are similar to interfaces. 抽象类类似于接口。You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. 您不能实例化它们,它们可能包含使用或不使用实现声明的方法的混合。However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods. 但是,对于抽象类,您可以声明非静态和最终的字段,并定义公共、受保护和私有的具体方法。With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. 对于接口,所有字段都自动是公共的、静态的和最终的,并且您声明或定义的所有方法(作为默认方法)都是公共的。In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.此外,您只能扩展一个类,不管它是否抽象,而您可以实现任意数量的接口。

Which should you use, abstract classes or interfaces?您应该使用哪一种,抽象类还是接口?

An example of an abstract class in the JDK is AbstractMap, which is part of the Collections Framework. JDK中抽象类的一个例子是AbstractMap,它是集合框架的一部分。Its subclasses (which include HashMap, TreeMap, and ConcurrentHashMap) share many methods (including get, put, isEmpty, containsKey, and containsValue) that AbstractMap defines.它的子类(包括HashMapTreeMapConcurrentHashMap)共享AbstractMap定义的许多方法(包括getputisEmptycontainsKeycontainsValue)。

An example of a class in the JDK that implements several interfaces is HashMap, which implements the interfaces Serializable, Cloneable, and Map<K, V>. JDK中实现多个接口的类的一个示例是HashMap,它实现了Serializable接口、Cloneable接口和Map<K, V>接口。By reading this list of interfaces, you can infer that an instance of HashMap (regardless of the developer or company who implemented the class) can be cloned, is serializable (which means that it can be converted into a byte stream; see the section Serializable Objects), and has the functionality of a map. 通过阅读此接口列表,可以推断HashMap的实例(无论实现该类的开发人员或公司是谁)可以克隆,是可序列化的(这意味着它可以转换为字节流;请参阅可序列化对象一节),它还具有映射的功能。In addition, the Map<K, V> interface has been enhanced with many default methods such as merge and forEach that older classes that have implemented this interface do not have to define.此外,Map<K, V>接口已通过许多默认方法(如mergeforEach)得到了增强,实现此接口的旧类不必定义这些方法。

Note that many software libraries use both abstract classes and interfaces; the HashMap class implements several interfaces and also extends the abstract class AbstractMap.注意,许多软件库同时使用抽象类和接口;HashMap类实现了几个接口,还扩展了抽象类AbstractMap

An Abstract Class Example抽象类示例

In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. 在面向对象的绘图应用程序中,可以绘制圆、矩形、直线、贝塞尔曲线和许多其他图形对象。These objects all have certain states (for example: position, orientation, line color, fill color) and behaviors (for example: moveTo, rotate, resize, draw) in common. 这些对象都具有某些共同的状态(例如:位置、方向、线颜色、填充颜色)和行为(例如:移动到、旋转、调整大小、绘制)。Some of these states and behaviors are the same for all graphic objects (for example: position, fill color, and moveTo). 其中一些状态和行为对于所有图形对象都是相同的(例如:位置、填充颜色和移动到)。Others require different implementations (for example, resize or draw). 其他需要不同的实现(例如,调整大小或绘制)。All GraphicObjects must be able to draw or resize themselves; they just differ in how they do it. 所有GraphicObject必须能够绘制或调整自身大小;他们只是在做这件事的方式上有所不同。This is a perfect situation for an abstract superclass. 对于抽象超类来说,这是一个完美的情况。You can take advantage of the similarities and declare all the graphic objects to inherit from the same abstract parent object (for example, GraphicObject) as shown in the following figure.您可以利用相似性并声明所有图形对象从同一抽象父对象(例如GraphicObject)继承,如下图所示。

Classes Rectangle, Line, Bezier, and Circle Inherit from GraphicObject

Classes Rectangle, Line, Bezier, and Circle Inherit from GraphicObject类矩形、直线、贝塞尔和圆继承自GraphicObject

First, you declare an abstract class, GraphicObject, to provide member variables and methods that are wholly shared by all subclasses, such as the current position and the moveTo method. 首先,声明一个抽象类GraphicObject,以提供所有子类完全共享的成员变量和方法(如当前位置和moveTo方法)。GraphicObject also declares abstract methods for methods, such as draw or resize, that need to be implemented by all subclasses but must be implemented in different ways. GraphicObject还为需要由所有子类实现但必须以不同方式实现的方法(如drawresize)声明抽象方法。The GraphicObject class can look something like this:GraphicObject类可以如下所示:

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

Each nonabstract subclass of GraphicObject, such as Circle and Rectangle, must provide implementations for the draw and resize methods:GraphicObject的每个非抽象子类(如CircleRectangle)必须提供draw方法和resize方法的实现:

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

When an Abstract Class Implements an Interface当抽象类实现接口时

In the section on Interfaces, it was noted that a class that implements an interface must implement all of the interface's methods. 接口一节中,注意到实现接口的类必须实现接口的所有方法。It is possible, however, to define a class that does not implement all of the interface's methods, provided that the class is declared to be abstract. 但是,如果类被声明为abstract类,则可以定义一个不实现所有接口方法的类。For example,

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

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

In this case, class X must be abstract because it does not fully implement Y, but class XX does, in fact, implement Y.在这种情况下,类X必须是abstract,因为它没有完全实现Y,但类XX实际上实现了Y

Class Members类成员

An abstract class may have static fields and static methods. 抽象类可以有静态字段和静态方法。You can use these static members with a class reference (for example, AbstractClass.staticMethod()) as you would with any other class.您可以将这些静态成员与类引用(例如AbstractClass.staticMethod())一起使用,就像与任何其他类一起使用一样。


Previous page: Writing Final Classes and Methods
Next page: Summary of Inheritance