Search code examples
javainheritanceinterfacejava-8default-method

Call default method from other interface in another default method


This code crashes:

public class MyClass {
    public static void main(String args[]) {
      Person person = new Person();
      person.selectMe();
    }
}

class Entity {}

interface EntityNameable<T extends Entity> {
  default String getSomething() {
    return "";
  } 
}

interface EntityNameableSelectable<T extends EntityNameable> {
  default String selectMe() { 
    return ((EntityNameable) this).getSomething();
  } 
}

class Person extends Entity implements EntityNameableSelectable {

}

This code can be executed by copy pasting it into https://www.jdoodle.com/online-java-compiler

Exception in thread "main" java.lang.ClassCastException: Person cannot be cast to EntityNameable
    at EntityNameableSelectable.selectMe(MyClass.java:18)
    at MyClass.main(MyClass.java:4)

It crashes because person can not be casted to EntityNameable. Why not? A person is always an Entity, EntityNamable and EntityNameableSelectable right?

I am also wondering why I need to cast this to EntityNameable to call method getSomething, as every implementing class should have that method. Why is the cast needed? It has to do something with the crash...


Solution

  • I am also wondering why I need to cast this to EntityNameable to call method getSomething, as every implementing class should have that method.

    EntityNameableSelectable is not an EntityNameable. EntityNameableSelectable does not extend that interface, so no methods are inherited.

    Probably, you wanted EntityNameableSelectable to extend EntityNameable, so you would be able to call getSomething().

    interface EntityNameableSelectable<T extends Entity> extends EntityNameable<T> {
        default String selectMe() {
            return getSomething();
        }
    }
    

    A Person is always an Entity, EntityNamable and EntityNameableSelectable, right?

    Only if EntityNameableSelectable extends EntityNameable or Person implements EntityNameable.

    If you defined EntityNameableSelectable as I mentioned above, the Person class would look like:

    class Person extends Entity implements EntityNameableSelectable<Person> {}