参数化方法的动态多态性
Dynamic Polymorphism with Parametrized methods
我想清楚地了解动态多态性。
当 child class 中的方法被 over-ridden 重载时,我无法弄清楚方法调用。
这里是 Parent class:
Parent Class:
public class Parent {
void print(Parent parent){
System.out.println("I am parent classes only print method.");
}
}
Child Class:
public class Child extends Parent {
void print(Child child) {
System.out.println("I am child class' child print method.");
}
void print(Parent parent) {
System.out.println("I am Child class' parent print method ");
}
}
这是来电者class。
public class Caller {
public static void main(String[] args) {
Parent p = new Parent();
Child c = new Child();
Parent pc = new Child();
p.print(p);
p.print(c);
p.print(pc);
c.print(p);
c.print(c);
c.print(pc);
pc.print(p);
pc.print(c);
pc.print(pc);
}
}
我可以在控制台中看到输出,但无法理解方法调用背后的原因。
这个问题看起来像 difference-between-method-overloading-and-overriding
的重复
覆盖(多态)和重载之间存在核心区别。
覆盖(多态性)在运行时确定。
方法重载在 编译时 .
确定
编译器根据可用的具体类型识别要调用的方法。
所以 c.print(c);
是唯一与签名匹配的调用:Child.print(final Child child)
我们只考虑两个对象,一个是P(Parent)
,第二个是C(Child)
。现在 P 只能看到它可以访问的那些方法和变量。在我们的例子中,它只能访问父 class' 打印方法。因此,每当您使用父对象调用打印方法时,它只会调用父对象 class 的打印方法。
p.print(p);
p.print(c);
p.print(pc);
表示以上所有行都将调用父级 class 的打印方法,因为父级无法访问子级的方法。
child的对象如变量pc
赋值给parent,会调用childclass的重写方法,也就是childclass的parent方法
pc.print(p);
pc.print(c);
pc.print(pc);
现在对于使用child class C 的方法,方法调用有两种可能性,一种是接受parent as an argument
的print 方法,第二种是接受child as an argument
。所以这完全取决于您在方法调用中传递的参数。
c.print(p);
c.print(c);
c.print(pc);
在第一次和第三次调用中,您将父对象作为参数传递给方法,因此编译器会根据传递的参数动态识别应调用哪个方法,因此子 class 的父方法将被调用当父对象作为参数传递时,else child class' child 方法将被调用。
工作很简单——重载在编译时解决,覆盖在运行时解决(多态性)。
那么,让我们看看在您的每个方法调用中发生了什么...
我们将忽略使用 Parent p = new Parent();
的调用,因为它没有重载或覆盖,所有方法调用将直接使用父方法的单一方法 "I am parent classes only print method."
.
还要注意,编译器只关心变量的引用类型。
运行时只关心 实际对象的类型 .
因此,在语句 Parent pc = new Child()
中,编译时 对 pc
的决定将引用 Parent
和任何 runtime 对 pc
的决定将参考 Child
。
这是其他方法调用的逻辑,
c.print(p);
//Compiler resolves that `print(Parent)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
c.print(c);
//Compiler resolves that `print(Child)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' child print method "
c.print(pc);
//Compiler resolves that `print(Parent)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
pc.print(p);
//Compiler resolves that `print(Parent)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
pc.print(c); //PAY ATTENTION TO THIS...
//Compiler resolves that `print(Parent)` method should be called.
// This is because PC is Parent type reference and compiler doesn't find `print(Child)` in Parent class, so it uses `print(Parent)`.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
pc.print(pc);
//Compiler resolves that `print(Parent)` method should be called.
// This is because Compiler knows only about the variable's reference type (And PC is of type Parent). Hence `print(Parent)` would be chosen.
//Runtime resolves that child objects method should be called.
//During runtime, the type of the actual object is used. And PC is referring to an Child object... So `pc.print(...)` will call the child's method.
//Prints "I am Child class' parent print method "
我想清楚地了解动态多态性。 当 child class 中的方法被 over-ridden 重载时,我无法弄清楚方法调用。
这里是 Parent class:
Parent Class:
public class Parent {
void print(Parent parent){
System.out.println("I am parent classes only print method.");
}
}
Child Class:
public class Child extends Parent {
void print(Child child) {
System.out.println("I am child class' child print method.");
}
void print(Parent parent) {
System.out.println("I am Child class' parent print method ");
}
}
这是来电者class。
public class Caller {
public static void main(String[] args) {
Parent p = new Parent();
Child c = new Child();
Parent pc = new Child();
p.print(p);
p.print(c);
p.print(pc);
c.print(p);
c.print(c);
c.print(pc);
pc.print(p);
pc.print(c);
pc.print(pc);
}
}
我可以在控制台中看到输出,但无法理解方法调用背后的原因。
这个问题看起来像 difference-between-method-overloading-and-overriding
的重复覆盖(多态)和重载之间存在核心区别。
覆盖(多态性)在运行时确定。 方法重载在 编译时 .
确定编译器根据可用的具体类型识别要调用的方法。
所以 c.print(c);
是唯一与签名匹配的调用:Child.print(final Child child)
我们只考虑两个对象,一个是P(Parent)
,第二个是C(Child)
。现在 P 只能看到它可以访问的那些方法和变量。在我们的例子中,它只能访问父 class' 打印方法。因此,每当您使用父对象调用打印方法时,它只会调用父对象 class 的打印方法。
p.print(p);
p.print(c);
p.print(pc);
表示以上所有行都将调用父级 class 的打印方法,因为父级无法访问子级的方法。
child的对象如变量pc
赋值给parent,会调用childclass的重写方法,也就是childclass的parent方法
pc.print(p);
pc.print(c);
pc.print(pc);
现在对于使用child class C 的方法,方法调用有两种可能性,一种是接受parent as an argument
的print 方法,第二种是接受child as an argument
。所以这完全取决于您在方法调用中传递的参数。
c.print(p);
c.print(c);
c.print(pc);
在第一次和第三次调用中,您将父对象作为参数传递给方法,因此编译器会根据传递的参数动态识别应调用哪个方法,因此子 class 的父方法将被调用当父对象作为参数传递时,else child class' child 方法将被调用。
工作很简单——重载在编译时解决,覆盖在运行时解决(多态性)。
那么,让我们看看在您的每个方法调用中发生了什么...
我们将忽略使用 Parent p = new Parent();
的调用,因为它没有重载或覆盖,所有方法调用将直接使用父方法的单一方法 "I am parent classes only print method."
.
还要注意,编译器只关心变量的引用类型。 运行时只关心 实际对象的类型 .
因此,在语句 Parent pc = new Child()
中,编译时 对 pc
的决定将引用 Parent
和任何 runtime 对 pc
的决定将参考 Child
。
这是其他方法调用的逻辑,
c.print(p);
//Compiler resolves that `print(Parent)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
c.print(c);
//Compiler resolves that `print(Child)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' child print method "
c.print(pc);
//Compiler resolves that `print(Parent)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
pc.print(p);
//Compiler resolves that `print(Parent)` method should be called.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
pc.print(c); //PAY ATTENTION TO THIS...
//Compiler resolves that `print(Parent)` method should be called.
// This is because PC is Parent type reference and compiler doesn't find `print(Child)` in Parent class, so it uses `print(Parent)`.
//Runtime resolves that child objects method should be called.
//Prints "I am Child class' parent print method "
pc.print(pc);
//Compiler resolves that `print(Parent)` method should be called.
// This is because Compiler knows only about the variable's reference type (And PC is of type Parent). Hence `print(Parent)` would be chosen.
//Runtime resolves that child objects method should be called.
//During runtime, the type of the actual object is used. And PC is referring to an Child object... So `pc.print(...)` will call the child's method.
//Prints "I am Child class' parent print method "