问题描述
代码是这样的:
class Main {
public static void main(String args[]) {
Person p1 = new Student();
Person p3 = new Teacher();
Student p4 = new Student();
OnlineLecture lec3 = new OnlineLecture();
lec3.addAttendant(p1);
lec3.addAttendant(p3);
lec3.addAttendant(p4);
}
}
abstract class Person {
public void join(Lecture lec) {
System.out.println("Joining "+lec);
}
public void join(OnlineLecture lec) {
System.out.println("Joining "+lec);
}
}
class Student extends Person {
public void join(Lecture lec) {
System.out.println("Student joining "+lec);
}
}
class Teacher extends Person {
public void join(OnlineLecture lec) {
System.out.println("Teacher joining "+lec);
}
}
class Lecture {
public void addAttendant(Person p) {
p.join(this);
}
public String toString() {
return "a lecture";
}
}
class OnlineLecture extends Lecture {
public String toString() {
return "an online lecture";
}
}
我不明白为什么我得到的输出是这样的:
Student joining an online lecture
Joining an online lecture
Student joining an online lecture
在 lec3 上调用的 'addAttendant' 方法中的 'join(this)' 不应该导致 'join(OnlineLecture lec3)',因此给出这个
Joining an online lecture
Teacher joining an online lecture
Joining an online lecture
作为输出?
解决方法
多态与重载
多态性
- 当调用
reference.method()
时表现出多态 - 这本质上是基于
object
引用的实际reference
类型的动态行为 - 这是查找表(如 C++ 中的 vmt)发挥作用的地方
- 根据引用指向的对象,运行时将决定要调用的实际方法
重载
- 编译时决策中的方法重载
- 方法的签名在编译时是固定的
- 根据方法的参数类型展示的任何多态性都不需要运行时查找
- 参数只是上下文中方法的参数,它不关心类型表现出的多态性
当前示例中发生了什么?
static class Lecture {
public void addAttendant(Person p) {
p.join(this);
}
}
- 假设有一个 Lecture 的子类覆盖
addAttendant
,那么当有人在 {{1} 的引用类型上调用方法时,多态可以根据object
类型控制调用哪个方法} 或其Lecture
之一。 - 但是,对于最终将落在
subclass(es)
上的任何调用,与Lecture.addAttendant
匹配的方法签名是p.join(this)
(即使可以动态引用join(Lecture)
) .即使p
引用的对象可能是多态类型,这里也没有多态性。
- 在
addAttendant
方法中,this
中的p.join(this)
是持有Lecture
类,因为在子类中没有addAttendant
的实现。因此,它调用join(Lecture lec)
方法。它忽略OnlineLecture
行为。
class Lecture {
public void addAttendant(Person p) {
p.join(this);
}
}
解决这种模棱两可行为的一种方法是在 OnlineLecture 子类中实现 @Override
方法 addAttendant(Person p)
:
public class InheritanceProblem {
public static void main(String args[]) {
Person p1 = new Student();
Person p3 = new Teacher();
Student p4 = new Student();
OnlineLecture lec3 = new OnlineLecture();
lec3.addAttendant(p1);
lec3.addAttendant(p3);
lec3.addAttendant(p4);
}
}
abstract class Person {
public void join(Lecture lec) {
System.out.println("Joining " + lec);
}
public void join(OnlineLecture lec) {
System.out.println("Joining " + lec);
}
}
class Student extends Person {
public void join(Lecture lec) {
System.out.println("Student joining " + lec);
}
}
class Teacher extends Person {
public void join(OnlineLecture lec) {
System.out.println("Teacher joining " + lec);
}
}
class Lecture {
public void addAttendant(Person p) {
p.join(this);
}
public String toString() {
return "a lecture";
}
}
class OnlineLecture extends Lecture {
@Override
public void addAttendant(Person p) {
p.join(this);
}
public String toString() {
return "an online lecture";
}
}
输出:
Joining an online lecture
Teacher joining an online lecture
Joining an online lecture