关于超类引用和子类对象的混淆
Posted
技术标签:
【中文标题】关于超类引用和子类对象的混淆【英文标题】:Confusion about superclass references and subclass objects 【发布时间】:2012-05-08 05:12:18 【问题描述】:我对此代码有一些疑问:
class superclass
void bark()
class subclass extends superclass
void bark()
public static void main(String[] args)
superclass refvar = new subclass();
refvar.bark();
为什么在这种情况下,无论孩子有没有方法,父母都必须有方法?我被告知在编译时引用变量是超类类型,所以编译器在编译时检查超类中的这个方法;准确吗?
当编译器读取bark()
时,它如何知道下一步要去哪里?我知道子方法会覆盖它,但我想知道它首先进入超类方法或子类,以及为什么。
为什么子类需要一个范围更广的访问修饰符?
【问题讨论】:
这是基本的面向对象编程原则。请仔细阅读此链接:docs.oracle.com/javase/tutorial/java/IandI/override.html 【参考方案1】:refvar
被声明为 superclass
对象,这就是为什么必须在 superclass
中声明 bark()
才能编译 refvar.bark()
。
它查找实例对象的bark()
实现。
在更窄的范围内覆盖某些东西没有多大意义。
【讨论】:
【参考方案2】:为什么在这种情况下父级必须要有方法, 孩子有没有?
您的示例在静态类型为superclass
的对象上调用bark()
- 如果superclass
没有声明方法bark()
,编译器不会知道这将是一个有效调用。
我被告知在编译时 引用变量是超类类型,所以编译器检查 编译时超类中的此方法;准确吗?
是的,事实上这就是我上面所说的。
当编译器读取
bark()
时,它如何知道下一步要去哪里?一世 知道子方法会覆盖它,但我想先知道它 转到超类方法或子类,以及为什么。
实际上,编译器下一步不会去任何地方。编译时重要的是bark()
是对superclass
类型对象的有效调用。只有在运行时调用才会被分派到subclass
中声明的bark()
覆盖。
为什么子类需要一个范围更广的访问修饰符?
我假设你的意思是子类的重写方法。澄清一下,它必须具有同等或更广泛的访问权限。它不能具有更窄访问权限的原因是因为这会破坏超类定义的合同。
例如,如果您被允许将subclass
中的bark()
更改为private
,那么理论上对该方法的调用不应在subclass
之外工作。但它需要工作,因为superclass
没有将bark()
设为私有:
class ClassInTheSamePackageAsTheOtherTwo
public static void main(String[] args)
superclass refvar = new subclass();
refvar.bark(); //as far as the compiler knows, this call is valid
【讨论】:
以上是关于关于超类引用和子类对象的混淆的主要内容,如果未能解决你的问题,请参考以下文章