简体   繁体   中英

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...

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

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

A Person extends Entity and implements EntityNameableSelectable , but it doesn't implement EntityNameable , no.

I don't know exactly what you're trying to do, but I suspect <T extends EntityNameable> is not doing what you want it to do. Try having EntityNameableSelectable extend EntityNameable instead:

interface EntityNameableSelectable extends EntityNameable {
  default String selectMe() { 
    return getSomething();
  } 
}

Similarly, making EntityNameable have a generic T parameter may not be correct either. In your sample code T isn't doing anything, so you might just remove it.

interface EntityNameable {
  default String getSomething() {
    return "";
  } 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM