为什么超类不能调用子类的方法?

问题描述 投票:0回答:1

我是一所高中的计算机科学老师,我正在用 Java 教授多态性。我的学生问我这个问题,我没有很好的答案。

假设我有一个 Employee 类。另外,我有一个 Lawyer 类,它是 Employee 的子类。现在假设方法 sue() 是在 Lawyer 类中定义的,但不在 Employee 类中。鉴于所有这些,以下代码将导致错误:

Employee ed = new Lawyer();
ed.sue();

问题是,为什么Java语言是这样构建的,这会导致错误?所有Lawyers都可以起诉,而ed是指向Lawyer对象的引用,所以ed不应该可以起诉吗?

这与人们在现实世界中、在计算机编程环境之外的随意对话中所期望的逻辑推理完全相反。假设我在办公楼里与首席执行官交谈,他说:

“这是埃德,我的一名员工,他是一名律师。不是我公司的每个员工都可以起诉人,但是律师可以起诉人。”

如果我听到首席执行官这么说,我就会得出结论,Ed 可以起诉人。

我在这个比喻中遗漏了什么吗?基本上我是说这段代码:

Employee ed = new Lawyer();

类似于以下语句:

“这是埃德,我的一名员工,他是一名律师。”

我还想说,当我们在 Lawyer 类中定义 sue() 方法,而不是在 Employee 类中时,这相当于说“不是每个员工都可以起诉,但律师可以起诉。”

顺便说一下,我知道 Java 中有一些方法可以绕过这个限制。例如,我可以让艾德扮演一名律师。

Employee ed = new Lawyer();
((Lawyer)ed).sue();

这不会导致错误。

或者,我可以首先简单地使用律师推荐信:

Lawyer ed = new Lawyer();
ed.sue();

这不会导致错误。

或者,我可以在 Employee 类中定义 sue() 方法,这样律师的 sue() 版本就会覆盖 Employee 的版本,然后原来的两行代码就可以正常运行而不会出现错误。

但是为什么我们需要使用这些解决方法呢?为什么指向子类对象的超类引用不能调用子类的方法?为什么 Java 是这样构建的?

java inheritance polymorphism subclass superclass
1个回答
0
投票

这不是“Java 中的限制”。静态类型允许我们对引用可以引用的类型做出非常有用的声明。

Employee ed
告诉您,您不能假设
ed
指的是
Lawyer
,并且您可以将对
Doctor
的引用分配给
ed
。能够表达这些约束并让编译器检查它们,可以使您的代码更易于理解,并消除错误来源。

看看你的解决方法:

Employee ed = new Lawyer();
((Lawyer)ed).sue();

如果

ClassCastException
不引用
ed
,则会抛出
Lawyer

如果给

sue()
添加一个
Employee
方法,你将如何为
Lawyer
以外的子类实现它?

唯一正确的解决方案是:

Lawyer ed = new Lawyer();
ed.sue();

明确约束

ed
必须引用
Lawyer
实例。

© www.soinside.com 2019 - 2024. All rights reserved.