试图理解 Java 中的继承

Trying to understand inheritance in Java

我觉得我对 Java 中的继承有很好的理解,但我正在为以下情况而苦苦挣扎:

public class SuperClass {

    private String name;
    private int age;

    public SuperClass(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void sharedMethod() {
        System.out.println("I'm a shared method in the SuperClass");
    }

}


public class SubClass extends SuperClass {

    public SubClass(String name, int age) {
        super(name, age);
    }

    public void sharedMethod() {
        System.out.println("I'm a shared method in the SubClass");
    }

    public void subMethod() {
        System.out.println("I'm subMethod");
    }

}


public class Main {

    public static void main(String args[]) {

        SuperClass test = new SubClass("Laura", 30);

        test.sharedMethod();

        test.subMethod(); // causes an error
    }
}

我主要是在努力理解使用 SuperClass test = new SubClass("Laura", 30); 时这里实际创建的是什么(这似乎只在 SubClass 扩展 SuperClass 时有效 - 如果没有 Casting 怎么可能?) .

我不明白的原因是因为我可以调用 sharedMethodSubClass 方法打印出文本(所以大概 SubClass 覆盖了 SuperClass 方法),但我根本无法从 SubClass 调用 subMethod。抱歉,如果我没有很好地表达出来,我似乎无法理解所引用的内容,可以使用哪些方法,为什么要这样做,为什么 SubClass 覆盖方法 if该方法是共享的,但不能以其他方式调用。

通过 SuperClass test = new SubClass("Laura", 30),您创建了一个 SubClass 实例,但通过 SuperClass.

引用了它

在编译阶段,编译器发现SuperClass没有方法subMethod,所以编译出错。

在运行时,JVM发现test实际上是一个SubClass,所以sharedMethod来自SubClass

public void sharedMethod() {
    System.out.println("I'm a shared method in the SubClass");
}

将被执行。

假设你有一个你告诉别人你有一辆车:

class Vehicle {

  public void drive() {
    System.out.println("Driving vehicle");
  }
}

也就是说,你告诉的人知道你有能力开车......但是,然后你有一辆摩托车:

class Motorcycle extends Vehicle {

  public void wheely() {
    System.out.println("Doing a wheely");
  }

  public void drive() {
    System.out.println("Driving motorcycle");
  }
}

可以drive()因为它是Vehicle,也可以wheely()。但是,您从未告诉他们您拥有的车辆类型是摩托车。所以,他们知道你最多能做的就是开车。

此人的知识水平与对象参考相似:

Vehicle vehicle = new Motorcycle();

Vehicle 引用只知道你是Vehicle。 "HOW"你开车不重要,它只知道你会开车。因此,当您调用 drive() 时,它将驱动 Motorcycle 驱动(覆盖方法),但您仍在驱动。

但是,如果您更具体地告诉别人您拥有的车辆类型是摩托车,那么您就是在向他们提供有关您车辆性能的更多信息。

Motorcycle motorcycle = new Motorcycle();

你知道,因为它是 Vehicle,它仍然可以做车辆可以做的所有事情 drive()。但是,由于您现在有对子 class 的引用,您更了解它可以做什么 - wheely().

编译器无法做出假设,因此如果您创建一个不太具体的引用 Vehicle v(超级 class),编译器将只访问它确定知道的该对象的元素有权访问。如果您进行更具体的引用(子 class),那么您就是在告诉编译器更多关于该对象可以做什么的信息。