在 Java 中,在继承该方法的子类上调用的超类方法中,'this' 表示什么?

In Java, what does 'this' indicate in a superclass method called on a subclass that inherits that method?

代码是这样的:

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

作为输出?

多态与重载

多态性

  1. 调用 reference.method() 时显示多态性
  2. 这本质上是基于 reference
  3. 引用的实际 object 类型的动态行为
  4. 这是查找表(如 c++ 中的 vmt)发挥作用的地方
  5. 根据引用指向的对象,运行时将决定调用的实际方法

超载

  1. 编译时决定方法重载
  2. 方法的签名在编译时固定
  3. 根据方法的参数类型显示的任何多态性都不需要运行时查找
  4. 参数只是上下文中方法的参数,它不关心类型表现出的多态性

当前示例发生了什么?

    static class Lecture {
        public void addAttendant(Person p) {
            p.join(this);
        }
    }
  1. 假设有一个 Lecture 的子 class 覆盖 addAttendant,那么当某人在引用上调用方法时,多态性可以根据 object 类型控制将调用哪个方法Lecture 的类型或其 subclass(es) 之一。
  2. 但是,对于最终将落在 Lecture.addAttendant 上的任何调用,与 p.join(this) 匹配的方法签名是 join(Lecture)(即使 p 可以是动态的参考)。这里没有多态性,即使 this 引用的对象可能是多态类型。
  • addAttendant 方法中,p.join(this) 中的 this 是 hold Lecture class,因为在 child 中没有实现 addAttendant class。因此,它调用 join(Lecture lec) 方法。它忽略 OnlineLecture 行为。
class Lecture {
    public void addAttendant(Person p) {
        p.join(this);
    }
}

解决这种不明确行为的一种方法是,在 OnlineLecture subclass 中实现 @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