java继承和后期绑定

时间:2015-03-01 18:17:24

标签: java inheritance late-binding

我理解以下代码如何工作,基于多态和动态绑定。 Java在某种程度上能够在运行时弄清楚因为vh是一个MotorBike,我们应该调用MotorBike的move()方法。

class Vehicle{
    public void move(){
        System.out.println(“Vehicles can move!!”);
    }
}

class MotorBike extends Vehicle{
    public void move(){
        System.out.println(“MotorBike can move and accelerate too!!”);
    }
}

class Test{
    public static void main(String[] args){
        Vehicle vh=new MotorBike();
        vh.move();    // prints MotorBike can move and accelerate too!!
    }
}

我不明白为什么以下代码会中断。我所做的唯一改变是从Vehicle类中删除move()方法。现在我收到一个编译错误,上面写着“找不到符号 - 方法move()”。为什么会这样?为什么上一个示例有效并且此代码不起作用?

class Vehicle{
}

class MotorBike extends Vehicle{
    public void move(){
        System.out.println(“MotorBike can move and accelerate too!!”);
    }
}

class Test{
    public static void main(String[] args){
        Vehicle vh=new MotorBike();
        vh.move();    // compile error
    }
}

1 个答案:

答案 0 :(得分:0)

Java有两个密切相关的概念,它们都是相关的:

  • 每个表达式都有一个类型,它是在编译时确定的。变量vh的类型为Vehicle,因此表达式vh(仅包含该变量)的类型为Vehicle
    • 顺便说一下,表达式new MotorBike()的类型为MotorBike,但由于这是Vehicle的子类型,编译器可以从前者转换为后者。 / LI>
  • 每个对象都有一个运行时类型 - 它所属的实例 - 在运行时确定。 new MotorBike()使用运行时类型MotorBike创建一个对象。

当您编写vh.move()时,如果Vehicle类没有名为move的方法,则编译器不知道您在谈论什么。

如果Vehicle 有一个名为move的方法,那么编译器可以很好地编译它,并将它留给运行时来检查实际的运行时类型相应的实例并发送到正确的方法。 (或者如果 没有相应的实例,则提出NullPointerException,因此没有相关的运行时类型。)

有一些语言,通常称为"动态输入" (或"无类型"或"动态"),没有 type 的概念,只有运行时的概念 - 输入的。这些语言包括Perl,Python,JavaScript等等。在这些语言中,vh.move()的模拟在所有情况下都会被接受,并且运行时会在调用之前验证该方法是否存在。但Java程序员更喜欢使用更智能的编译器,这有助于我们在编译类型中检测更多错误。