繁体   English   中英

为什么Java编译器决定是否可以基于“引用”类型调用方法而不是实际的“对象”类型?

[英]Why does Java compiler decide whether you can call a method based on the “reference” type and not on actual “object” type?

我只是想知道为什么Java编译器决定是否可以调用基于“引用”类型的方法而不是实际的“对象”类型? 为了解释我想引用一个例子:

class A {
void methA() {
    System.out.println("Method of Class A.");
} 
}

class B extends A {
void methB() {
    System.out.println("Method of Class B.");
}
public static void main(String arg[]) {
    A ob = new B();
    ob.methB();       // Compile Time Error
}
}

这将产生编译时错误,即方法methB()class A找不到,尽管对象引用“ob”包含由方法methB()组成的class B的对象。 原因是Java Compiler检查Class A (引用类型)中的方法而不是Class B (实际对象类型)。 所以,我想知道这背后的原因是什么。 为什么Java Compiler在Class A中查找方法,为什么不在Class B中(实际的对象类型)?

假设你有一个Animal类和一个扩展 AnimalDog类。 现在,如果Animal定义了一个名为speak()的方法,Dog定义了一个名为bark()的方法。 如果您这样做:

Animal a = new Dog();

这意味着你指着一只狗并说它是一只动物。 当您将狗视为动物(而不是狗)时,您只能调用为动物定义的方法,而不是狗。

在编译期间,编译器会检查是否在引用类型中定义了被调用的方法。

通过将变量声明为A类,您基本上隐藏了它实际上是一个子类型的事实。 没有看到类型B的方法是标准行为,这在(严格类型的)面向对象中是必不可少的。

很简单,编译器不知道变量的类型。 与上面描述的场景不同,实际的“对象”类型通常并不明显。 这就是“对象”类型是运行时类型的原因:它在运行时已知。

想象一下像这样的方法:

public static void process(A ob) {
    ob.methB(); //how do you know if this is valid?
}

public static void main(String[] args) {
    process(new B()); //would make the above call valid
    process(new A()); //would make the above call invalid
}

简而言之,您允许变量具有使您的调用无效的运行时类型。 可能是有效的,但如果依赖于methB() ,则必须将B作为参数。

回到你的代码示例,这个例子没有任何意义:

A ob = new B();
//why would you declare ob as A if you are storing a B inside it
//this is only useful if you want to store different types of objects in it at some point
//however, that's not the case, because in the next line:
ob.methB(); //you're calling methB()

你的疑问很好,但它是一种哎呀。 您正在为超类分配一个子类对象,因此我将只向调用者公开超类的方法。

简单地说,假设A类作为具有2个方法和B的接口是实现类,其中包含10个方法。 但是如果你尝试用接口A为该类创建对象,它将只暴露2个方法。 在您的情况下应用相同的逻辑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM