-1

I understand how the following code works, based on polymorphism and dynamic binding. Java is somehow able to figure out at runtime that because vh is a MotorBike, we should call MotorBike's move() method.

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!!
    }
}

What I don't understand is why the following code breaks. the only change I've made is to delete the move() method from the Vehicle class. Now I get a compile error that says "cannot find symbol - method move()". Why is this so? Why does the previous example work and this code doesn't?

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
    }
}
ruakh
  • 175,680
  • 26
  • 273
  • 307
  • 1
    Because you have told the compiler that the `vh` reference points to a `Vehicle`, and all `Vecicle`s don't have a `move()` method. – Keppil Mar 01 '15 at 18:19

1 Answers1

0

Java has two closely-related concepts that are both relevant here:

  • Every expression has a type, which is determined at compile-time. The variable vh has type Vehicle, so the expression vh (consisting of just that variable) has type Vehicle.
    • The expression new MotorBike(), by the way, has type MotorBike, but since that's a subtype of Vehicle, the compiler can convert from the former to the latter.
  • Every object has a runtime-type — the class that it's an instance of — which is determined at runtime. new MotorBike() creates an object with runtime-type MotorBike.

When you write vh.move(), if the Vehicle class doesn't have a method called move, then the compiler has no idea what you're talking about.

If Vehicle does have a method called move, then the compiler can compile it just fine, and leaves it to the runtime to examine the actual runtime-type of the corresponding instance and dispatch to the right method. (Or to raise a NullPointerException if there is no corresponding instance, and therefore no relevant runtime-type.)

There are some languages, generally called "dynamically typed" (or "untyped" or "dynamic"), that don't have this concept of type, and only the concept of runtime-type. Such languages include Perl, Python, JavaScript, and many others. In such languages, the analogue of vh.move() would be accepted just fine in all cases, and the runtime would verify that the method exists before calling it. But Java programmers prefer a somewhat smarter compiler, that helps us detect more bugs at compile-type.

ruakh
  • 175,680
  • 26
  • 273
  • 307