Java继承

继承可以定义为一个类获取另一个类的属性(方法和字段)的过程。 通过使用继承,可以按层次顺序管理信息。

继承其他类的属性的类称为子类(或派生类),被其它继承其属性的类称为超类(或基类,父类)。

1. extends关键字

extends是用于继承类属性的关键字。 以下是extends关键字的语法。

语法

class Super {
   .....
   .....
}
class Sub extends Super {
   .....
   .....
}

示例代码

以下是演示Java继承的示例。 在此示例中,可以观察两个类,即CalculationMyCalculation

使用extends关键字,MyCalculation继承Calculation类的方法:addition()Subtraction()

将以下程序复制并粘贴到名为MyCalculation.java 的文件中。


// 文件:MyCalculation.java
class Calculation {
    int z;

    public void addition(int x, int y) {
        z = x + y;
        System.out.println("两个数的和是:" + z);
    }

    public void Subtraction(int x, int y) {
        z = x - y;
        System.out.println("两个数的差是:" + z);
    }
}

public class MyCalculation extends Calculation {
    public void multiplication(int x, int y) {
        z = x * y;
        System.out.println("两个数的乘积是:" + z);
    }

    public static void main(String args[]) {
        int a = 20, b = 10;
        MyCalculation demo = new MyCalculation();
        demo.addition(a, b);
        demo.Subtraction(a, b);
        demo.multiplication(a, b);
    }
}

执行上面示例代码,得到以下结果:

两个数的和是:30
两个数的差是:10
两个数的乘积是:200

在给定的程序中,当创建MyCalculation类的对象时,会在对象内部创建超类(Calculation)的内容的副本。就可以使用子类的对象,来访问超类的成员。

Java继承

超类引用变量可以包含子类对象,但是使用该变量只能访问超类的成员,因此要访问两个类的成员,建议始终为子类创建引用变量。

如果考虑上面的程序,可以实例化下面给出的类。 但是使用超类引用变量(在本例中为cal),无法调用方法multiplication(),因为方法multiplication()属于子类MyCalculation的方法。

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

2. super关键字

super关键字与this关键字类似,以下是使用super关键字的注意事项。

  • 如果它们具有相同的名称,superthis关键字用于区分超类的成员和子类的成员。
  • super关键字用于从子类调用超类构造函数。

区分成员

如果一个类继承了另一个类的属性。如果超类的成员具有与子类相同的名称,要区分这些变量,使用super关键字显示地访问父类的属性,如下所示 -

super.variable; // 访问父类变量
super.method();// 访问父类方法

示例代码

本节提供了一个演示如何使用super关键字用法的程序。

在给定的程序中有两个类,即SubclassSuperclass,它们都有一个名为display()的方法,具有不同的实现,以及一个num变量,具有不同的值。 调用两个类的display()方法并打印两个类的变量num的值。 在这里,使用super关键字来区分超类和子类的成员。

将程序复制并粘贴到名为Subclass.java的文件中。


// Subclass.java
class Superclass {
    int num = 20;

    // 超类方法
    public void display() {
        System.out.println("这是超类的显示方法");
    }
}

public class Subclass extends Superclass {
    int num = 10;

    // 子类方法
    public void display() {
        System.out.println("这是子类的显示方法");
    }

    public void my_method() {
        // 初始化子类
        Subclass sub = new Subclass();

        // 调用子类的display()方法
        sub.display();

        // 调用父类的display()方法
        super.display();

        // 打印子类变量num的值
        System.out.println("子类中名为num的变量的值:" + sub.num);

        // 打印父类变量num的值
        System.out.println("超类中名为num的变量的值:" + super.num);
    }

    public static void main(String args[]) {
        Subclass obj = new Subclass();
        obj.my_method();
    }
}

执行上面示例代码,得到以下结果:

这是子类的显示方法
这是超类的显示方法
子类中名为num的变量的值:10
超类中名为num的变量的值:20

3. 调用超类构造函数

如果一个类继承另一个类的属性,则子类自动获取超类的默认构造函数。 但是如果要调用超类的参数化构造函数,则需要使用super关键字,如下所示。

super(parm-values);

示例代码

下面给出的程序中演示了如何使用super关键字来调用超类的参数化构造函数。 这个程序包含一个超类和一个子类,超类中包含一个接受整数值的参数化构造函数,在子类中使用super关键字来调用超类的参数化构造函数。

将以下程序复制并粘贴到名为Subclass.java 的文件中 -

// Subclass.java
class Superclass {
    int age;

    Superclass(int age) {
        this.age = age;
    }

    public void getAge() {
        System.out.println("超类中名为age的变量的值是: " + age);
    }
}

public class Subclass extends Superclass {
    Subclass(int age) {
        super(age);
    }

    public static void main(String argd[]) {
        Subclass s = new Subclass(24);
        s.getAge();
    }
}

执行上面示例代码,得到以下结果:

超类中名为age的变量的值是: 24

4. IS-A关系

IS-A是这样的一种说法:对象A是对象B的一种。下面来看看如何使用extends关键字实现继承。

public class Animal {

}

// Mammal IS-A Animal
public class Mammal extends Animal {

}

// Reptile对象是(IS-A)对象 Animal 的一种
public class Reptile extends Animal {
}

// Dog对象是(IS-A)对象 Mammal 的一种
public class Dog extends Mammal {

}

基于上面的例子,在面向对象的术语中,以下是真的 -

  • 动物(Animal)类是哺乳动物(Mammal)类的超类。
  • 动物(Animal)类是爬行动物(Reptile)类的超类。
  • 哺乳动物(Mammal)类和爬行动物(Reptile)是Animal类的子类。
  • 狗(Dog)是哺乳动物(Mammal)类和动物(Animal)类的子类。

现在,如果使用IS-A关系,可以这样描述 -

  • Mammal IS-A Animal
  • Reptile IS-A Animal
  • Dog IS-A Mammal
  • 因此: Dog IS-A Animal

通过使用extends关键字,子类将能够继承超类的所有属性,但超类的私有属性除外。可以确保Mammal使用instanceof运算符来判断它是Animal类型。

示例代码


class Animal {
}

class Mammal extends Animal {
}

class Reptile extends Animal {
}

public class Dog extends Mammal {

    public static void main(String args[]) {
        Animal a = new Animal();
        Mammal m = new Mammal();
        Dog d = new Dog();

        System.out.println(m instanceof Animal);
        System.out.println(d instanceof Mammal);
        System.out.println(d instanceof Animal);
    }
}

执行上面示例代码,得到以下结果:

true
true
true

通过上面的学习,现在对extends关键字应该有很好的理解了,下面来看看implements关键字如何用于获取IS-A 关系。

通常,implements关键字与类一起用于继承接口的属性。 接口永远不能被类扩展。

示例

public interface Animal {

}

public class Mammal implements Animal {

}

public class Dog extends Mammal {

}

4.1. instanceof关键字

使用instanceof运算符来检查确定Mammal是否是Animal类的一种,Dog是否是Animal类的一种。

示例

interface Animal{}
class Mammal implements Animal{}

public class Dog extends Mammal {

   public static void main(String args[]) {
      Mammal m = new Mammal();
      Dog d = new Dog();

      System.out.println(m instanceof Animal);
      System.out.println(d instanceof Mammal);
      System.out.println(d instanceof Animal);
   }
}

执行上面示例代码,得到以下结果:

true
true
true

5. HAS-A关系

这些关系主要基于用法。 这决定了某某类HAS-A是否有某种东西。这种关系有助于减少代码重复和错误。

示例

public class Vehicle{}
public class Speed{}

public class Van extends Vehicle {
   private Speed sp;
}

上面示例中Vehicle类有HAS-A Speed类。 通过为Speed提供一个单独的类,不必将属于Speed类的整个代码放在Van类中,这样就可以在多个应用程序中重用Speed类。

在面向对象的功能中,用户无需担心哪个对象正在进行实际工作。要实现这一点,Van类隐藏了用户的实现细节。 因此,基本上发生的事情是用户会要求Van类执行某个操作,而Van类要么自己完成工作要么要求另一个类执行操作。

6. 继承的类型

如下所示,有各种各样类型的继承。

继承的类型

需要注意:Java不支持多重继承。 在Java中,一个类不能扩展多个类。 因此以下代码是非法的 -

// 非法声明类
public class extends Animal, Mammal{}

但是,一个类可以实现一个或多个接口,这有助于Java实现多重继承特性。


上一篇: Java异常处理 下一篇: Java快速入门