I have the following code in Scala:
trait Component {
def state : String
def name: String
}
case class AComponent( id : String) extends Component {
def state = name + ":" + id
def name = "A"
}
trait ComponentDecoratorA extends Component {
abstract override def name = "ByADecorated:" + super.name
}
trait ComponentDecoratorB extends Component {
abstract override def name = "ByBDecorated:" + super.name
}
object Run
{
def main (args : Array[String]) = {
val c = new AComponent ("42") // static decoration
with ComponentDecoratorA with ComponentDecoratorB
println( c.state)
}
The output is:
ByBDecorated:ByADecorated:A:42
I am new in Scala, but I know that we can inherit from the trait in object creation to limit the trait to the object. But as I have understood it correctly we are inheriting from ComponentDecoratorA and ComponentDecoratorB when creating the object. But why don't we get a conflict for the name method? And the output shows that the name methods of all three classes are called. How can this happen?
val c = new AComponent ("42") // static decoration
with ComponentDecoratorA with ComponentDecoratorB
Why do we need new
although we are using a case class?
And how does it get the result ByBDecorated:ByADecorated:A:42?
When you say
new Class1 with Trait1
you are creating the equivalent of an anonymous class in Java. E.g. in Java you could saynew Class1(){ /* add additional implementation details here*/ }
In terms of the order of inclusions when combining the
this.name + this.super.name
strings, that's called the "diamond problem" and is solved by what Scala calls "type linearization:" https://www.safaribooksonline.com/blog/2013/05/30/traits-how-scala-tames-multiple-inheritance/