[英]Why do I get a compile-time error when calling a subclass method using superclass reference?
我知道在方法重写的情况下会发生多态。 但是我对以下内容有些困惑。
class A {
public void hi() {
System.out.println("A "+this.getClass().getName());
}
}
class B extends A {
public void bye() {
System.out.println("B "+this.getClass().getName());
}
}
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
A a = new B();
a.hi();
a.bye();
}
}
输出:
Main.java:35: error: cannot find symbol
a.bye();
^
symbol: method bye()
location: variable a of type A
1 error
为什么这会产生编译时错误?
在a = new B()
, B
类对象是在运行时创建的,因此a
一个指向B
类型对象的引用变量。
现在,如果我们调用B
的类方法bye()
,为什么它是编译器错误?
的a
变量可以在运行时包含类的实例A
或任何亚类的A
。 因此,您只能为该变量调用类A
方法。
编译器仅在确定哪些方法调用有效时才关心变量的编译时类型。
变量a
的声明类型为A。编译器在运行时不知道(也不应该知道)它的具体类型是B。它所知道的只是它是A,并且没有bye()
方法。在一个。
整个工作要做
A a = new B();
并不是
B a = new B();
明确表示a是A,并且可以有任何具体类型,只要conrete类型扩展了A。如果稍后找到更好的A实现,则必须能够将该行更改为
A =新的BetterImplementation();
并编译代码。
多态性基本上是对象采取多种形式的能力。 由于您的父类引用的是子类对象,因此它是多态的。
Main.java:35: error: cannot find symbol
a.bye();
^
symbol: method bye()
location: variable a of type A
1 error
之所以出现此错误,是因为您试图从超类引用中调用子类的方法。
在这里,您可以将subClass对象ref分配给超类,这很好。 但是超类只能调用它自己的已知方法和数据。
A a = new B();
a.hi(); // member of super class
a.bye(); // Not a member a super class
将新的B
实例分配给类型A
的引用就像使它戴上了仅在A中定义的方法。 那就是您在A
处描述的接口。 即使该实例具有bye
的实现,您也只能访问hi
。
一种简单的理解方法是A a可能实际上指向B的对象,但是在编译期间编译器并不知道这一点。
编译器仅检查引用即“ a”,并查看其类(即“ A”)是否具有其引用“ a”正在尝试调用的方法。
在您的情况下,引用“ a”没有名为bye()的方法,因此根据编译器,无法进行此类调用,这就是您看到该错误的原因。
您只能从父类类型访问父类方法。
A a = new B();
解决方案1:
将父级更改为子级( B b = new B ()
)并调用B方法。
解决方案2:
检查父对象是否为子对象的实例。 如果是,则将父项强制转换为Child并调用该方法。
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
A a = new B();
a.hi();
if ( a instanceof B){
((B)a).bye();
}
}
}
输出:
A B
B B
看看instanceof上的oracle文档页面
instanceof运算符将对象与指定类型进行比较。 您可以使用它来测试对象是实现特定接口的类的实例,子类的实例还是类的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.