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()
中。如果在 Machine
和 Camera
构造函数中添加一些输出,也许会更容易理解。
Camera() {
// the Machine() constructor will be called and executed HERE
this.mach_id = id;
id++;
}
我认为从 OO 的角度来考虑这一点是值得的,而不仅仅是作为构造函数的机制 - 从长远来看,这将有助于您的编码。
考虑 extends
关系的一种简单方法是原样。换句话说,您的代码表示 Camera
是 Machine
。因此,任何适用于 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
。所以它给新对象 1
的 mach_id
,并且 id
递增。
Camera cam = new Camera();
直接调用Camera
构造函数。
任何构造函数做的第一件事就是调用超类的构造函数。如果您没有明确告诉它这样做,它将隐式调用超类的无参数构造函数。所以现在调用 Machine
构造函数。
它设置此对象的 mach_id
的值(将其视为 Machine
到 id
的当前值,即 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
变量中,但这不会改变上述任何事实。您调用的方法仍然来自超类方法。
我编写了一个代码,其中每个机器对象都有一个使用静态字段自动生成的 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()
中。如果在 Machine
和 Camera
构造函数中添加一些输出,也许会更容易理解。
Camera() {
// the Machine() constructor will be called and executed HERE
this.mach_id = id;
id++;
}
我认为从 OO 的角度来考虑这一点是值得的,而不仅仅是作为构造函数的机制 - 从长远来看,这将有助于您的编码。
考虑 extends
关系的一种简单方法是原样。换句话说,您的代码表示 Camera
是 Machine
。因此,任何适用于 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
。所以它给新对象 1
的 mach_id
,并且 id
递增。
Camera cam = new Camera();
直接调用Camera
构造函数。
任何构造函数做的第一件事就是调用超类的构造函数。如果您没有明确告诉它这样做,它将隐式调用超类的无参数构造函数。所以现在调用 Machine
构造函数。
它设置此对象的 mach_id
的值(将其视为 Machine
到 id
的当前值,即 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
变量中,但这不会改变上述任何事实。您调用的方法仍然来自超类方法。