Reputation: 43
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
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