文档

Java™ 教程-Java Tutorials 中文版
继承
Trail: Learning the Java Language
Lesson: Interfaces and Inheritance

继承

在前面的课程中,你已经多次看到 inheritance (继承)。在 Java 语言中,类可以从其他类 derived (派生),从而从那些类 inheriting (继承) 字段和方法。


定义: 从另一个类派生的类称为 subclass (子类)(也称为 derived class (派生类)extended class (扩展类) ,或 child class (子类))。从中派生子类的类称为 superclass (超类)(也称为 base class (基类)parent class (父类))。

除了 Object,它没有超类,每个类有且只有一个直接超类(单继承)。在没有任何其他显式超类的情况下,每个类都隐式地是 Object 的子类。

类可以派生自一个派生类,该派生类可以派生自一个派生类,依此类推,最终派生自最顶层的类 Object。这样的类被称为 descended (继承了) (译注:可以理解为后代,意会一下)继承链中的所有类延伸回 Object

继承的想法很简单但很强大:当你想创建一个新类并且已经有一个包含你想要的代码的类时,你可以从现有的类派生你的新类。在这样做时,你可以重用现有类的字段和方法,而无需自己编写(和调试!)它们。

子类从其超类继承所有 members (成员)(字段,方法和嵌套类)。构造函数不是成员,因此它们不能由子类继承的,但是可以从子类调用超类的构造函数。

Java 平台类层次结构

java.lang 包中定义的 Object 类定义并实现所有类共有的行为,包括你编写的类。在 Java 平台中,许多类直接从 Object 派生,其他类派生自其中一些类,依此类推,形成类的层次结构。

Java 平台中的所有类都是 Object 的后代

Java 平台中的所有类都是 Object 的后代

在层次结构的顶部,Object 是所有类中最一般的。层次结构底部附近的类提供更专业的行为。

继承的一个例子

以下是在“类和对象”类中提供的 Bicycle 类的可能实现的示例代码:

public class Bicycle {
        
    // the Bicycle class has three fields
    public int cadence;
    public int gear;
    public int speed;
        
    // the Bicycle class has one constructor
    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }
        
    // the Bicycle class has four methods
    public void setCadence(int newValue) {
        cadence = newValue;
    }
        
    public void setGear(int newValue) {
        gear = newValue;
    }
        
    public void applyBrake(int decrement) {
        speed -= decrement;
    }
        
    public void speedUp(int increment) {
        speed += increment;
    }
        
}

MountainBike 类的类声明是 Bicycle 的子类,可能如下所示:

public class MountainBike extends Bicycle {
        
    // the MountainBike subclass adds one field
    public int seatHeight;

    // the MountainBike subclass has one constructor
    public MountainBike(int startHeight,
                        int startCadence,
                        int startSpeed,
                        int startGear) {
        super(startCadence, startSpeed, startGear);
        seatHeight = startHeight;
    }   
        
    // the MountainBike subclass adds one method
    public void setHeight(int newValue) {
        seatHeight = newValue;
    }   
}

MountainBike 继承 Bicycle 的所有字段和方法,并添加字段 seatHeight 以及设置它的方法。除了构造函数之外,就好像你已经从头开始编写了一个新的 MountainBike 类,有四个字段和五个方法。但是,你不必完成所有工作。如果 Bicycle 类中的方法很复杂并且需要花费大量时间来调试,这将特别有价值。

你可以在子类中执行的操作

无论子类所在的包是什么,子类都会继承其父类的所有 publicprotected 成员。如果子类与其父类在同一个包中,它还会继承父类的 package-private 成员。你可以按原样使用继承的成员,替换它们,隐藏它们或用新成员补充它们:

本课程的以下部分将扩展这些主题。

超级私有会员

子类不继承其父类的 private 成员。但是,如果超类具有访问其 private 字段的 public 或 protected 方法,则子类也可以使用这些方法。

嵌套类可以访问其封闭类的所有 private 成员 - 包括字段和方法。因此,子类继承的 public 或 protected 嵌套类可以间接访问超类的所有 private 成员。

转换对象

我们已经看到一个对象是实例化它的类的数据类型。例如,如果我们写

public MountainBike myBike = new MountainBike();

那么 myBike 的类型为 MountainBike

MountainBike 来自 BicycleObject。因此,MountainBikeBicycle 并且也是 Object,它可以在任何调用 Bicycle Object 的地方使用。

反过来不一定正确:Bicycle 可能是 一个 MountainBike,但不一定如此。类似地,Object 可能是 一个 BicycleMountainBike,但不一定如此。

Casting (转换) 显示在继承和实现允许的对象中使用一种类型的对象代替另一种类型。例如,如果我们写

Object obj = new MountainBike();

然后 obj 既是 Object 又是 MountainBike(直到 obj 分配另一个 不是 MountainBike 的对象)。这称为 implicit casting (隐式转换)

另一方面,如果我们写

MountainBike myBike = obj;

我们会得到编译时错误,因为编译器不知道 objMountainBike。但是,我们可以 告诉 编译器我们承诺分配一个 MountainBikeobj ,通过 explicit casting (显示转换)

MountainBike myBike = (MountainBike)obj;

此强制转换插入运行时检查 obj 被分配了一个 MountainBike,以便编译器可以安全地假设 objMountainBike。如果 obj 在运行时不是 MountainBike,则会抛出异常。


注意: 你可以使用 instanceof 运算符对特定对象的类型进行逻辑测试。这可以避免由于不正确的强制转换而出现运行时错误。例如:
if (obj instanceof MountainBike) {
    MountainBike myBike = (MountainBike)obj;
}

这里 instanceof 运算符验证 obj 是否引用 MountainBike,以便我们可以使用转换,而不会抛出运行时异常。



Previous page: Questions and Exercises: Interfaces
Next page: Multiple Inheritance of State, Implementation, and Type