在 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
作为输出?
多态与重载
多态性
- 调用
reference.method()
时显示多态性
- 这本质上是基于
reference
引用的实际 object
类型的动态行为
- 这是查找表(如 c++ 中的 vmt)发挥作用的地方
- 根据引用指向的对象,运行时将决定调用的实际方法
超载
- 编译时决定方法重载
- 方法的签名在编译时固定
- 根据方法的参数类型显示的任何多态性都不需要运行时查找
- 参数只是上下文中方法的参数,它不关心类型表现出的多态性
当前示例发生了什么?
static class Lecture {
public void addAttendant(Person p) {
p.join(this);
}
}
- 假设有一个 Lecture 的子 class 覆盖
addAttendant
,那么当某人在引用上调用方法时,多态性可以根据 object
类型控制将调用哪个方法Lecture
的类型或其 subclass(es)
之一。
- 但是,对于最终将落在
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
代码是这样的:
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()
时显示多态性 - 这本质上是基于
reference
引用的实际 - 这是查找表(如 c++ 中的 vmt)发挥作用的地方
- 根据引用指向的对象,运行时将决定调用的实际方法
object
类型的动态行为
超载
- 编译时决定方法重载
- 方法的签名在编译时固定
- 根据方法的参数类型显示的任何多态性都不需要运行时查找
- 参数只是上下文中方法的参数,它不关心类型表现出的多态性
当前示例发生了什么?
static class Lecture {
public void addAttendant(Person p) {
p.join(this);
}
}
- 假设有一个 Lecture 的子 class 覆盖
addAttendant
,那么当某人在引用上调用方法时,多态性可以根据object
类型控制将调用哪个方法Lecture
的类型或其subclass(es)
之一。 - 但是,对于最终将落在
Lecture.addAttendant
上的任何调用,与p.join(this)
匹配的方法签名是join(Lecture)
(即使p
可以是动态的参考)。这里没有多态性,即使this
引用的对象可能是多态类型。
- 在
addAttendant
方法中,p.join(this)
中的this
是 holdLecture
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