如果方法调用是动态绑定的,那么编译器为什么抱怨
对于类型 B 未定义方法 run()
为什么编译器检查是否存在类 b 中运行的方法
这是代码
import java.lang.*;
public class Program
{
public static void main(String [] args)
{
B a = new A();
a.run();//compiler complains at this line.
a.p(10);
a.p(10.0);
}
}
class B {
public void p(int i)
{
System.out.println(i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println(i);
}
public void run(){
}
}
设计上是一种静态类型语言,这意味着编译器必须知道并能够保证该方法的实现存在于每个具体对象中。(Maxim Shoustin的回答用一个例子很好地说明了这个设计决策背后的原因。
如果编译器在没有任何保证的情况下假设未知对象碰巧具有特定方法,它将使Java成为鸭子类型语言。这可能有自己的优势,但它不符合Java的设计目标。
实际上,在静态类型语言中,虚拟(意味着非最终)方法(例如run()
方法)是动态解析的,但用于解析它们的策略仍在编译时编写。例如,该策略可能涉及在许多多态性实现中读取 vTable 的正确偏移量(包含该对象的虚拟方法的实际实现地址的表) - 利用语言的类型安全性在动态调度期间获得一些性能。
对于类型 B 未定义方法 run()
该错误是不言自明的。B
类型没有名为 .run()
的方法
B a = new A()
意味着您的变量a
属于 B
类型,这就是系统对变量a
的全部了解。
如果您执行了Object s = new String()
然后执行了s.toLowerCase()
它也会失败,因为变量 s
属于 Object
类型而不是 String
类型。
无论您的变量是什么类型,都是您可以对该类型调用的唯一行为。
它很容易显示:
让我稍微更改一下您的代码:
- B = 动物
- A = 牛
替换后:
public class Program
{
public static void main(String [] args)
{
Animal a = new Cow();
a.sayMooo();//compiler complains at this line. You try to animal to say "moo"?
a.speed(10);
a.speed(10.0);
}
}
class Animal {
public void speed(int i)
{
System.out.println(i*2);
}
}
class Cow extends Animal{
public void p(int i)
{
System.out.println(i);
}
public void sayMooo(){
}
}
并非所有动物都是牛
当然
并非所有动物都会说"哞哞"
但
所有的牛都是动物