Search code examples
scalainheritancetraitsself-type

What is more Scala idiomatic: trait TraitA extends TraitB or trait TraitA { self: TraitB => }


Apart from the inheritance aspect, is there a difference between the following class templates:

1| trait TraitA extends TraitB

2| trait TraitA { self: TraitB => }

I would like to split responsibilities between TraitA and TraitB but the former cannot function without the latter.

How would you express this intent? To me solution [2] would be the more natural approach. However I do not want to put the burden on implementers mixing in what needs to be mixed in anyway.


Solution

  • My preference is generally [1] because, as you say, the implementor is not burdened to mix in (a sub-type of) TraitB. Perhaps [2] is preferable if, for some reason, it is desirable not to inherit the concrete implementations in TraitB and force the implementor to make a choice among sub-types of TraitB. Still, [1] is just as flexible.

    I tend to use [2] only where necessary, such as when the type isn't a known class or trait,

    // Here, Matrix cannot extend type parameter Repr
    trait Matrix[+Repr <: Matrix[Repr]] { self: Repr =>
      ...
    }
    

    Update. Here's another minor difference,

    trait B
    trait A { self: B => }
    def g(ab: A): B = ab // Type mismatch: found A, required B
    

    It's a little annoying an optional restriction not to be able to use A as a B, even though the type is incorporated.