# 继承

> 原文： [https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html](https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html)

在前面的课程中，您已经多次看到 _ 继承 _。在 Java 语言中，类可以是来自其他类的 _ 派生 _，从而 _ 从这些类继承 _ 字段和方法。

* * *

**Definitions:** A class that is derived from another class is called a _subclass_ (also a _derived class_, _extended class_, or _child class_). The class from which the subclass is derived is called a _superclass_ (also a _base class_ or a _parent class_).

Excepting `Object`, which has no superclass, every class has one and only one direct superclass (single inheritance). In the absence of any other explicit superclass, every class is implicitly a subclass of `Object`.

Classes can be derived from classes that are derived from classes that are derived from classes, and so on, and ultimately derived from the topmost class, `Object`. Such a class is said to be _descended_ from all the classes in the inheritance chain stretching back to `Object`.

* * *

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

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

## Java 平台类层次结构

`java.lang`包中定义的 [`Object`](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html) 类定义并实现所有类共有的行为 - 包括您编写的行。在 Java 平台中，许多类直接从`Object`派生，其他类派生自其中一些类，依此类推，形成类的层次结构。

<center>![All Classes in the Java Platform are Descendants of Object](img/de7eb1c95f2611f2583ebbd6951d1e98.jpg)

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

</center>

在层次结构的顶部，`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;
    }

}

```

作为`Bicycle`的子类的`MountainBike`类的类声明可能如下所示：

```
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`类中的方法很复杂并且需要花费大量时间来调试，这将特别有价值。

## 您可以在子类中执行的操作

子类继承其父类的所有 _public_ 和 _protected_ 成员，无论子类在哪个包中。如果子类与其父类在同一个包中，它也继承父 _ 包私有 _ 成员。您可以按原样使用继承的成员，替换它们，隐藏它们或用新成员补充它们：

*   继承的字段可以直接使用，就像任何其他字段一样。
*   您可以在子类中声明一个与超类中的字段相同的字段，因此 _ 隐藏 _ 它（不推荐）。
*   您可以在子类中声明不在超类中的新字段。
*   继承的方法可以直接使用。
*   您可以在子类中编写一个新的 _ 实例 _ 方法，该方法与超类中的签名具有相同的签名，因此 _ 会覆盖 _ 它。
*   您可以在子类中编写一个新的 _ 静态 _ 方法，该方法与超类中的签名具有相同的签名，因此 _ 隐藏 _ 它。
*   您可以在子类中声明不在超类中的新方法。
*   您可以编写一个子类构造函数，它可以隐式地或使用关键字`super`来调用超类的构造函数。

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

## 超级私人会员

子类不继承其父类的`private`成员。但是，如果超类具有访问其私有字段的公共或受保护方法，则子类也可以使用这些方法。

嵌套类可以访问其封闭类的所有私有成员 - 包括字段和方法。因此，子类继承的公共或受保护嵌套类可以间接访问超类的所有私有成员。

## 投射物体

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

```
public MountainBike myBike = new MountainBike();

```

那么`myBike`的类型为`MountainBike`。

`MountainBike`来自`Bicycle`和`Object`。因此，`MountainBike`是`Bicycle`并且也是`Object`，并且可以在需要`Bicycle`或`Object`对象的任何地方使用。

反过来不一定正确：`Bicycle` _ 可能是 _ a `MountainBike`，但不一定如此。类似地，`Object` _ 可以是 _ a `Bicycle`或`MountainBike`，但不一定如此。

_Casting_ 显示在继承和实现允许的对象中使用一种类型的对象代替另一种类型。例如，如果我们写

```
Object obj = new MountainBike();

```

那么`obj`既是`Object`又是`MountainBike`（直到`obj`分配另一个对象为 _ 而不是 _ a `MountainBike`）。这称为 _ 隐式投射 _。

另一方面，如果我们写作

```
MountainBike myBike = obj;

```

我们会得到编译时错误，因为编译器不知道`obj`是`MountainBike`。但是，我们可以 _ 告诉 _ 编译器我们承诺通过 _ 显式转换将`MountainBike`分配给`obj`：_

```
MountainBike myBike = (MountainBike)obj;

```

此转换插入运行时检查，为`obj`分配`MountainBike`，以便编译器可以安全地假设`obj`是`MountainBike`。如果`obj`在运行时不是`MountainBike`，则会抛出异常。

* * *

**Note:** You can make a logical test as to the type of a particular object using the `instanceof` operator. This can save you from a runtime error owing to an improper cast. For example:

```
if (obj instanceof MountainBike) {
    MountainBike myBike = (MountainBike)obj;
}

```

这里`instanceof`运算符验证`obj`是否引用了`MountainBike`，这样我们就可以知道不会抛出运行时异常。

* * *