Java 多态行为

Java Polymorphism behaviour

我编写了一个代码,其中每个机器对象都有一个使用静态字段自动生成的 ID 'id'。我试图理解 JAVA 中的多态性。预期输出是 1 2 3 4 但我得到的输出是 1 2 4 6。有人能解释为什么会这样吗?

class Machine{
    static int id=1;
    private int mach_id;
    private String name;
    Machine(){
        this.mach_id = id;
        id++;
    }
    public int getId(){
        return this.mach_id;
    }

}

class Camera extends Machine {
    private int mach_id;
    Camera(){
        this.mach_id = id;
        id++;
    }

}


public class App {
    public static void main(String[] args){
        Machine mach = new Machine();
        Camera cam = new Camera();
        Machine mach1 = new Camera();
        Machine mach2 = new Camera();
        System.out.println(mach.getId());
        System.out.println(cam.getId());
        System.out.println(mach1.getId());
        System.out.println(mach2.getId());
    }
}

请注意,Camera 构造函数还调用了 Machine 构造函数。因此,每次创建 Camera 对象时,都会将 id 递增 2 – 一次在 Machine() 中,然后在 Camera() 中。如果在 MachineCamera 构造函数中添加一些输出,也许会更容易理解。

Camera() {
    // the Machine() constructor will be called and executed HERE
    this.mach_id = id;
    id++;
}

我认为从 OO 的角度来考虑这一点是值得的,而不仅仅是作为构造函数的机制 - 从长远来看,这将有助于您的编码。

考虑 extends 关系的一种简单方法是原样。换句话说,您的代码表示 CameraMachine。因此,任何适用于 Machine 的东西也适用于 Camera,并且您可以随时在需要 Machine 时使用 Camera

在您的例子中,您说的是 Machine 递增 id。你说过 Camera,以及 Machine 所做的一切(因为它是 Machine),递增 id。所以这自然意味着两个增量,一次是 Machine 一次是 Camera.

两个构造函数都设置了它们的id,然后递增。您的 main 方法创建了一台机器和三个摄像头。所以 ID 将是:

机器 id = 1 +1,编号 = 2 相机 ID = 2 +2,编号 = 4 相机 ID = 4 +2,编号 = 6 相机 ID = 6

因此输出 1、2、4、6

正如 Robin 所说,这完全是关于 inheritance 概念而不是 polymorphism

在 Java 中,不带参数的基 class 构造函数会在派生 class 构造函数中自动调用。这很有道理,

if Human class 有一个 walk 方法

然后你从 class Student s = new Student()

创建一个实例

继承自 Human 如果 Human 的构造函数未被调用,则对象 s 无法调用未在内存中初始化的方法 walk

所以超级构造函数在派生class构造函数之前被调用。

事情是这样的:

Machine mach = new Machine();

直接调用Machine构造函数。 id 目前是 1。所以它给新对象 1mach_id,并且 id 递增。

Camera cam = new Camera();

直接调用Camera构造函数。

任何构造函数做的第一件事就是调用超类的构造函数。如果您没有明确告诉它这样做,它将隐式调用超类的无参数构造函数。所以现在调用 Machine 构造函数。

它设置此对象的 mach_id 的值(将其视为 Machineid 的当前值,即 2。然后递增 id.

现在 Camera 构造函数开始自己的工作。它采用 id 的当前值,当前为 3,将其放入 mach_id,并递增 id。现在是 4.

现在是棘手的部分。 Camera 中的 mach_id 隐藏了 Machine 中的 mach_id。但是 Machine 中的方法 getID() 没有看到 Camera 中定义的 mach_id。它看到 Machine 中的那个。因此,当您调用它时,它会从对超类构造函数的调用中获取值,即 2。它看不到您在 Camera 中创建的私有字段,也不知道它的值,即 3.

然后您再次构造新的 Camera 对象。您将它们放在 Machine 变量中,但这不会改变上述任何事实。您调用的方法仍然来自超类方法。