ryeguy
ryeguy

Reputation: 66851

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?

Upvotes: 0

Views: 1741

Answers (4)

Volty De Qua
Volty De Qua

Reputation: 289

You can specify the trait's subclass, though it will be redundant. Considering that this code

object TraitPulling {
  class A {
    val a = 0
    println("I am constructor of A")
  }
  trait T extends A { val t = 1 }
  class B extends T
  class C extends A with T    // though no T with A
  List(new T {}, new B(), new C()).foreach { e =>
    println(s"t: ${e.t}, a: ${e.a}")
  }
}

TraitPulling

gives the following output

I am constructor of A
I am constructor of A
I am constructor of A
t: 1, a: 0
t: 1, a: 0
t: 1, a: 0

we can deduce that since class A's content gets instantiated because it is implied (by trait T extends A), the three forms are semantically equivalent.

Upvotes: 0

0__
0__

Reputation: 67280

"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 }

Upvotes: 6

Julien Richard-Foy
Julien Richard-Foy

Reputation: 9663

What you can’t do is:

scala> class A2
defined class A2

scala> class B extends A2 with T
<console>:8: error: illegal inheritance; superclass A2
 is not a subclass of the superclass A
 of the mixin trait T
       class B extends A2 with T
                               ^

Actually, writing class B extends T is the same as writing class B extends A with T.

Upvotes: 1

Thomas Lockney
Thomas Lockney

Reputation: 2587

You're simply confused about what a trait is. Saying class B extends T simply means that you're "mixing in" the functionality of the trait to the class definition of B. So, everything defined in T or it's parent classes and traits, is available in B.

Upvotes: 0

Related Questions