Trait Similarity to Classes
Traits can have constructors! Wow, I wasn’t expecting that one. Just like a class, the constructor is embedded in the body of the trait itself. Every trait has one parameterless constructor. The fact that a trait has a parameterless constructor is the only technical difference between traits and classes. So anything you can do with a class, you can do with a trait!
trait Foo {
def bar(x: String)
def log(y: String) {}
// part of the constructor
val baz = 10
out.println('bats')
}
Trait constructors execute in the following order:
- The superclass constructor is called
- Traits are constructed left-to-right
- In each trait, its parents are constructed first
- If multiple traits share a common parent and the parent has already been constructed, it is not constructed again.
- the subclass constructor is called
If we want to evaluate some inherited logic from the fields of the file
logger, because of the construction order we need have one of two
options: lazy evalutaion, or early definition blocks. In some class
Foo which inherits from a FileLogger:
trait FileLogger extends Logger {
val filename: String
lazy val out = new PrintStream(filename)
def log(msg: String) { out.println(msg) } // No override needed
}
Evaluating out lazyly will give us time to instantiate filename
before running out. Alternatively we can define filename early in an
instance:
val foo = new { val filename = "myapp.log" } with Foo with FileLogger
or in the class definition:
class Foo extends {
val filename = "savings.log"
} with Account with FileLogger {
// Foo implementation
}
Since traits are technically the same as a class, but with that one hitch of being parameterless, it stands that a trait can extend a class and make it a superclass of any class mixing the trait.
For example we have a trait Foo extends ClassSuper and a
class Sub extends Foo. Then the superclass of Foo, ClassSuper will
be passed on to become the superclass of Sub. This is even okay if our
class extends a seperate class and only uses Foo as a trait so long as
all classes are a subclasses of the trait’s superclass. Only one
superclass can exist.