Traits as Interfaces
Let’s start with something familiar. A Scala trait can work exactly like a Java interface. For example:
trait Logger { def log(msg: String) // An abstract method }
A subclass can provide an implementation:
class ConsoleLogger extends Logger { // Use extends, not implements def log(msg: String) { println(msg) } // No override needed }
If you need more than one trait, add the others using the with keyword: All Java interfaces can be used as Scala traits.
class ConsoleLogger extends Logger with Cloneable with Serializable
Traits with def, val and var
Never use val
in a trait
for abstract members and use def
instead. See http://stackoverflow.com/questions/19642053/when-to-use-val-or-def-in-scala-traits.
Traits with Concrete Implementations
In Scala, the methods of a trait need not be abstract.
trait ConsoleLogger {
def log(msg: String) { println(msg) }
}
Here is an example of using this trait:
class SavingsAccount extends Account with ConsoleLogger { def withdraw(amount: Double) { if (amount > balance) log("Insufficient funds") else balance -= amount } ... }
Note the difference between Scala and Java. The SavingsAccount picks up a concrete implementation from the ConsoleLogger trait. This would not be possible with a Java interface.
Objects with Traits
You can add a trait to an individual object when you construct it.
trait Logged { def log(msg: String) { }//do nothing implementation }