Suggestion dealing with multiple traits and profile combinations in Scala

37 views Asked by At

I have a situation where I have several traits with each trait containing a set of methods. I have now to expose these functionalities to the external world through profiles. For example., a basic profile will be another trait, but this contains just the methods a and 2 from trait 1, methods 4 and 5 from trait 2 etc.,I can create these profiles as a new trait and repeat the method implementation, but how can I reuse the already defined methods in my trait and just create the profile traits more elegantly? For example.,

trait InternalTrait1 {
  def method1(int: Int): Int
  def method2(int: Int): Int
}

trait InternalTrait2 {
  def method3(int: Int): Int
  def method4(int: Int): String
}

I would now like to have:

    trait BasicProfile {
      this: InternalTrait1 with InternalTrait2 =>

      def method2(int: Int): Int = super.method2(int)
      def method4(int: Int): String = super.method4(int)
    }

I want to refer the method2 and method4 from Trait1 and Trait2 respectively. Any ideas? Self traits come to my mind, but not sure if that is a good idea?

1

There are 1 answers

16
Dmytro Mitin On BEST ANSWER

Could you introduce a couple of traits more (like Method2Doer and Method4Doer below)?

trait Method2Doer {
  def method2(int: Int): Int
}

trait Method4Doer {
  def method4(int: Int): String
}
  
trait InternalTrait1 extends Method2Doer {
  def method1(int: Int): Int
}

trait InternalTrait2 extends Method4Doer {
  def method3(int: Int): Int
}

trait BasicProfile extends Method2Doer with Method4Doer

If none of the traits are in IS-A relation and you'd prefer not to introduce new traits then you can try to replace inheritance with composition (HAS-A relation)

trait BasicProfile {
  val internalTrait1Inst: InternalTrait1
  val internalTrait2Inst: InternalTrait2
    
  def method2(int: Int): Int = internalTrait1Inst.method2(int)
  def method4(int: Int): String = internalTrait2Inst.method4(int)
}

or

trait BasicProfile {
  val internalTraitsInst: InternalTrait1 with InternalTrait2

  def method2(int: Int): Int = internalTraitsInst.method2(int)
  def method4(int: Int): String = internalTraitsInst.method4(int)
}

In principle you can use structural types

trait BasicProfile { this: {def method2(int: Int): Int; def method4(int: Int): String} =>
    
}