Jeff Xu
Jeff Xu

Reputation: 43

scala self type trait instantiation

Trait in scala is something like interface in Java or abstract class. Thus it is not possible to get an instance directly from a trait. But, I found a way to instantiate a trait. Here is what i do:

trait B {
  def bId = 1
}

trait A { self: B =>
  def aId = 2
}

val a = new A with B // The type of a is "A with B", a's value is $anon$1@6ad16c5d

and the following:

trait User {
  def name: String
}

trait DummyUser extends User {
  override def name: String = "foo"
}

trait Tweeter { self: User =>
  def tweet(msg: String) = println(s"$name: $msg")
}

val t = new Tweeter with User // This doesn't compile
val t = new Tweeter with User with DummyUser // This does work!
// t: Tweeter with User with DummyUser = $anon$1@72976b4
t.tweet("hello")  // result is: "foo: hello"

Both segments of code are working on Scala 2.12. In the all of them, there are only traits! No class at all.

How can trait work in this way?

Upvotes: 3

Views: 597

Answers (1)

chengpohi
chengpohi

Reputation: 14227

This instantiation like Java's Anonymous Classes instantiation, so when new Tweeter with User it's actually create a new anonymous instance for Tweeter with User Anonymous Classes.

And new Tweeter with User for this not compile, since it's losing the implementation of name method. actually you need to implement it like:

  val t = new Tweeter with User {
    override def name: String = "hello world"
  }

for new Tweeter with User with DummyUser you just need to state it as new Tweeter with DummyUser, Since DummyUser is subtype of User.

And there is a cake pattern in Scala for how to use self type to implement Dependency Injection.

Upvotes: 6

Related Questions