Search code examples
scalatraits

Why can't I specify a trait's subclass?


scala> class A
defined class A

scala> trait T extends A { val t = 1 }
defined trait T

//why can I do this?
scala> class B extends T
defined class B

scala> new B
res0: B = B@2e9c76

scala> res0.t
res1: Int = 1

I thought that when you write trait T extends A, it makes it so you can only put trait T on a class that is a subclass of A. Why can I put it on B, then? Is this only for when you mix it in? Why is this not possible when declaring the class?


Solution

  • "it makes it so you can only put trait T on a class that is a subclass of A"

    The feature you want is a self-type annotation. See also Daniel Sobral's answer to this question : What is the difference between self-types and trait subclasses? --> look for the links to dependancy-injection and cake-pattern.

    trait A { def t: Int }
    trait B {
      this: A => // requires that a concrete implementation mixes in from A
      def t2: Int = t // ...and therefore we can safely access t from A
    }
    
    // strangely this doesn't work (why??)
    def test(b: B): Int = b.t
    
    // however this does
    def test2(b: B): Int = b.t2
    
    // this doesn't work (as expected)
    class C extends B
    
    // and this conforms to the self-type
    class D extends B with A { def t = 1 }