1

Apologies if duplicate, don't know the right terminology for this question, so I didn't find anyone asking something similar.

I have two interfaces. Lets say Canine and Pet. Pet has a play method, which is abstract. Canine does NOT extend Pet. It has a default play method though, which matches the play method signature of Pet.

Dog is a class that implements both Canine and Pet. Dog would like to use Canine's default play method.

How would i go about implementing this cleanly? The only way I see is if I do something silly like this

class Dog implements Canine, Pet{
    public Dog(){
    }
    @Override
    public void play (String greeting) {
        Canine.super.play(greeting);
    }

}

interface Canine {
    default void play (String greeting) {
        System.out.println(greeting);
    }
}

interface Pet {
    void play (String greeting);
}

From what i can tell, in C++ you can declare that a class uses the default implementation of a method, instead of implementing it in said class. Is there a way to do something similar in java 8?

  • Have Canine extend Pet and remove the Pet interface from Dog. – Ryan Mar 09 '20 at 20:06
  • Well, this is just an example, where i replace the actual problem im working with with relative names. I CANT have Canine extend Pet, because in this situation, canine is irrelevant to pet, it only has one method in common. Dog is both canine and pet, but canine is not a pet. – Jakub Taraska Mar 09 '20 at 20:11
  • 1
    The is no alternative syntax to express this specific intent. Your solution is the canonical solution. – Holger Mar 10 '20 at 10:25
  • I disagree with Holger on this, having multiple interfaces with the same method signature is going to cause problems later. Assume you have a if-else block testing for type of Canine and of pet. The logic will take the first check, but you might want the second check in that context. I think it's a design flaw that will become a maintenance nightmare down the road. – Ryan Mar 10 '20 at 13:26

1 Answers1

1

This is already a clean approach. Just to make it a bit clearer, check the output from the following program where Dog extends Animal which too has a play method but that won't be called in presence of Canine's default play method.

class Animal {
    public Animal() {
    }

    public void play(String greeting) {
        System.out.println("Before greeting in Animal");
        System.out.println(greeting);
        System.out.println("After greeting in Animal");
    }
}

class Dog extends Animal implements Canine, Pet {
    public Dog() {
    }

    @Override
    public void play(String greeting) {
        System.out.println("Before greeting in Dog");
        Canine.super.play(greeting);
        System.out.println("After greeting in Dog");
    }
}

interface Canine {
    default void play(String greeting) {
        System.out.println("Before greeting in Canine");
        System.out.println(greeting);
        System.out.println("After greeting in Canine");
    }
}

interface Pet {
    void play(String greeting);
}

public class Main {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.play("Hello");
    }
}

Output:

Before greeting in Dog
Before greeting in Canine
Hello
After greeting in Canine
After greeting in Dog
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110