4

I am learning more about polymorphism and casting in Java. I was running some code and I am quite confused with the output. I would really appreciate it if someone can explain what the compiler is doing here.

When I wrote this code, I thought that since newCar() is being cast to Vehicle, I assumed it would use the default method that was written in the Vehicle interface. But it looks like it used the overridden method in Car.

Thanks in advance!!

public interface Vehicle {
 default boolean canFly() {return true;}
}

public class Car implements Vehicle {

 boolean canFly() {return false;}

 public static void main(String[] args) {
   Vehicle vehicle = (Vehicle) new Car();
   System.out.println(vehicle.canFly());
 }
}

I saw possible duplicates; however, the question was targeted to only classes. My question is specifically with interfaces.

abhivemp
  • 932
  • 6
  • 24

2 Answers2

3

The whole point of inheritance and polymorphing is that it doesn't matter what type the variable has, the actual type of the created object determines which method will be called.

There is no way for you to call the Vehicle version of the canFly method, since it has been overridden by the Car class, and the real object is a Car.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Understood. Does that mean if I used ```Vehicle``` while casting to my Car object, it does nothing? – abhivemp Jul 29 '19 at 18:30
  • @abhivemp Casting a Vehicle as a Car causes problems and casting a Car as a Vehicle simply changes the reference type, not the object itself. – Mihir Kekkar Jul 29 '19 at 18:32
  • @abhivemp Sorry, I don't understand that comment. – Andreas Jul 29 '19 at 18:33
  • "There is no way for you to call the ```Vehicle``` version of the ```canFly``` method, since it has been overridden by the ```Car``` class, and the real object is a ```Car```" -- So does this imply that ```(Vehicle) vehicle = (Vehicle) new Car();``` doesn't make any difference to ```Car vehicle = new Car();```? – abhivemp Jul 29 '19 at 18:46
  • 1
    @abhivemp Not to the call of `canFly`, but if you added a *new* method to `Car`, it cannot be called from a variable of type `Vehicle`, since the method isn't available to all vehicles. --- *Side note:* A type can implicitly be assigned to a super-type, so the cast is redundant. `Vehicle vehicle = new Car();` is perfectly valid. Any good IDE would have told you this, so I suggest you use one. – Andreas Jul 29 '19 at 20:45
1

The Lambda faq lists conflict resolution rules for default methods. First rule is:

Classes always win. A declaration in the class or a superclass takes priority over any default method declaration.

Because the class provides an implementation of the method, that always takes precedence over the default method on the interface. ("Default" means a fallback for cases where no implementation is provided otherwise.)

Casting only keeps the compiler from reporting an error due to some variable's type not matching the type of the thing being assigned to it. It's there for cases where you know it's ok to treat something as another type and you need to overrule the compiler. Casting has no effect at runtime, except to cause a ClassCastException to be thrown if the cast is erroneous. See here for more details.

TLDR: The idea that you could use casts to change what method gets called is not accurate.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276