Search code examples
javascalaoopmultiple-inheritancetraits

Scala choose which trait to implement from in case of conflicting signatures?


How to choose in Scala which trait to choose implementation from in case of conflicting method signatures?

Suppose the following Java interfaces:

interface Dog {
    default void makeSound() {
        System.out.println("Woof");
    }

    default void beHappy() {
        System.out.println("Wag tail");
    }
}

interface Cat {
    default void makeSound() {
        System.out.println("Meow");
    }

    default void beHappy() {
        System.out.println("Purrr");
    }
}

And now suppose I want a purring dog, without reimplementing anything:

public class PurringDog implements Dog, Cat {
    @Override
    public void makeSound() {
        Dog.super.makeSound();
    }

    @Override
    public void beHappy() {
        Cat.super.beHappy();
    }

    public static void main(String[] args) {
        PurringDog purringDog = new PurringDog();

        purringDog.makeSound(); //prints Woof
        purringDog.beHappy();   //prints Purrr
    }
}

How can this be achieved in Scala?


Solution

  • You can use super with a qualifier:

    trait Dog {
      def makeSound(): Unit = println("Woof")
      def beHappy(): Unit = println("Wag tail")
    }
    
    trait Cat {
      def makeSound(): Unit = println("Meow")
      def beHappy(): Unit = println("Purrr")
    }
    
    class PurringDog extends Dog with Cat {
      override def makeSound() = super[Dog].makeSound()
      override def beHappy() = super[Cat].beHappy()
    }
    
    object Test extends App {
      val purringDog = new PurringDog
      purringDog.beHappy()
      purringDog.makeSound()
    }
    

    Note that you can use the qualifier only for the traits you mix in directly (those appearing after an extends or a with), so crawling on the hierarchy (e.g. having a base trait Animal) won't work with qualifiers.