Java 子类方法被忽略

Java subclass method is getting ignored

我有这些 classes

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";}
}

然后在主要 class 我有这个

public 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);
}
}


为什么我得到这个:

Student joining an online lecture
Joining an online lecture
Student joining an online lecture

而不是这个:

Joining an online lecture
Teacher joining an online lecture
Joining an online lecture

如果我传递一个 OnlineLecture 实例,为什么代码表现得像一个 Lecture 实例?老师 class 覆盖了 join(OnlineLecture lec) 但来自家长 class 的那个仍然被调用。

这是由于 join() 签名在 Person 中的类型比 Student
中的类型更强 由于 Student 仅覆盖

中的 Lecture
  public void join(Lecture lec){System.out.println("Student joining "+lec);}

使用的方法来自父classPerson

  public void join(OnlineLecture lec){System.out.println("Joining "+lec);}

作为解决方案,使用给定的签名

正确覆盖 Student class 中的 join
public void join(OnlineLecture lec)

只有 class Lecture 定义了 addAttendant(Person p)。所以

中的this
public void addAttendant(Person p) {
 p.join(this);
}

将永远是 Lecture

并且由于 Student 覆盖了 join(Lecture lec),因此在 lec3.addAttendant(p1); 时调用了此覆盖方法,因为 p1Studentlec3 是还有一个Lecture

Teacher 仅覆盖 join(OnlineLecture lec) 而不是 join(Lecture lec)lec3.addAttendant(p3); 调用 Lecture.addAttendant(Person p) 其中 p == p3Teacherp.join(this); 中的 thisLecture 但不是 OnlineLecture。这就是无法调用 Teacher.join(OnlineLecture lec) 的原因,因为 this 不是 OnlineLecture,而是 Lecture。所以 Person.join(Lecture lec) 被调用了。

不太清楚使用复杂的继承和嵌套方法调用应该实现什么。所以这只是对正在发生的事情的描述。