Consider this example:
abstract class Writer {
def write(message: String): Unit
}
trait UpperCaseFilter extends Writer {
abstract override def write(message: String) =
super.write(message.toUpperCase)
}
trait LowerCaseFilter extends Writer {
abstract override def write(message: String) =
super.write(message.toLowerCase)
}
class StringWriter extends Writer {
val sb = new StringBuilder
override def write(message: String) =
sb.append(message)
override def toString = sb.toString
}
object Main extends App {
val writer = new StringWriter with UpperCaseFilter with LowerCaseFilter
writer.write("Hello, world!")
println(writer)
}
I was surprised by the output “HELLO, WORLD!” Why is the output not “hello, world!” or a compilation error?
The logic that decides it is called linearization. You can find more information about it here:
http://www.artima.com/pins1ed/traits.html#12.6
In your case the whole class hierarchy would linearized like this:
LowerCaseFilter
> UpperCaseFilter
> Writer
> StringWriter
> AnyRef
> Any
So, as you can see, UpperCaseFilter
was the last transformation that went to the StringWriter
.