scala的trait设计
Scala的trait设计,突破了Java的object model的继承机制的限制,实际上变成了一种模块化的设计。
具体来讲,Trait并不是一个interface,而是一个功能模块,允许用户把这个模块插入到class当中。
例子如下:
scala> class ServiceImportante(name: String) {
| def work(i: Int): Int = {
| println(s"ServiceImportante: Doing important work! $i")
| i + 1
| }
| }
defined class ServiceImportante
scala> val service1 = new ServiceImportante("uno")
service1: ServiceImportante = ServiceImportante@1c31408f
scala> (1 to 3) foreach (i => println(s"Result: ${service1.work(i)}"))
ServiceImportante: Doing important work! 1
Result: 2
ServiceImportante: Doing important work! 2
Result: 3
ServiceImportante: Doing important work! 3
Result: 4
如上所示,首先定义一个class,叫做ServiceImportante
。然后定义一个叫做Logging
的trait:
scala> trait Logging {
| def info (message: String): Unit
| def warning(message: String): Unit
| def error (message: String): Unit
| }
defined trait Logging
trait本身也可以继承,方法也可以直接在trait里面实现:
scala> trait StdoutLogging extends Logging {
| def info (message: String) = println(s"INFO: $message")
| def warning(message: String) = println(s"WARNING: $message")
| def error (message: String) = println(s"ERROR: $message")
| }
defined trait StdoutLogging
把trait作为功能模块插入到class当中:
scala> val service2 = new ServiceImportante("dos") with StdoutLogging {
| override def work(i: Int): Int = {
| info(s"Starting work: i = $i")
| val result = super.work(i)
| info(s"Ending work: i = $i, result = $result")
| result
| }
| }
service2: ServiceImportante with StdoutLogging = $anon$1@674fee6d
scala> (1 to 3) foreach (i => println(s"Result: ${service2.work(i)}"))
INFO: Starting work: i = 1
ServiceImportante: Doing important work! 1
INFO: Ending work: i = 1, result = 2
Result: 2
INFO: Starting work: i = 2
ServiceImportante: Doing important work! 2
INFO: Ending work: i = 2, result = 3
Result: 3
INFO: Starting work: i = 3
ServiceImportante: Doing important work! 3
INFO: Ending work: i = 3, result = 4
Result: 4
scala>
如果要重复使用上面的ServiceImportante with StdoutLogging
这个组合,也可以定义成一个新的class:
scala> class LoggedServiceImportante(name: String) extends ServiceImportante(name) with StdoutLogging
defined class LoggedServiceImportante
scala> val logged = new LoggedServiceImportante("logged")
logged: LoggedServiceImportante = LoggedServiceImportante@1d1bca3b
scala> logged.work(42)
ServiceImportante: Doing important work! 42
res15: Int = 43
以上。