Scala 的 Trait 结合了抽象类与接口的能力,通过混入来获得灵活的多态能力。
代码如下所示: FileAbility 提供了读取文件、处理文件的能力, 其中继承一个空实现的 Trait:LineHandler, 类似于模板方法模式; 在 ScalaTraitDemo 的 handleFile 方法中,动态定义了两个 Trait , 在新生成的 FileAbility 对象中混入了这两个 Trait 的功能,并且实现了链式处理,类似于装饰器模式。
package scalastudy.basic /** * Created by lovesqcc on 16-3-27. */ trait LineHandler { def handle(line: String):Any = {} }
package scalastudy.basic import scala.io.Source /** * Created by lovesqcc on 16-3-27. */ trait FileAbility extends LineHandler { def readFile(filename:String): String = { val fileSource = Source.fromFile(filename) try { return fileSource.mkString } finally { fileSource.close() } } def readFileLines(filename:String):List[String] = { val fileSource = Source.fromFile(filename) try { return fileSource.getLines().toList } finally { fileSource.close() } } def handleFile(filename:String):List[Any] = { return readFileLines(filename).map(handle(_)).toList } def handleFileWithNoReturn(filename:String, lineHandler: LineHandler):Unit = { readFileLines(filename).foreach { line => lineHandler.handle(line) } } }
package scalastudy.basic import java.util /** * Created by lovesqcc on 16-3-19. */ object ScalaTraitDemo extends App { launch() def launch(): Unit = { handleFile("/etc/passwd") } def handleFile(filename:String):Unit = { trait LinePrintHandler extends LineHandler { override def handle(line: String): Any = { println(line) } } val fileAbility = new FileAbility with LinePrintHandler fileAbility.handleFile(filename) trait LineSplitterHandler extends LineHandler { override def handle(line: String): Any = { return super.handle(line.split(":").mkString("(", ",", ")")) } } trait LineNumberHandler extends LineHandler { var id = 0 override def handle(line:String): Any = { id += 1 //println("number: " + line); return id + ": " + line } } val fileAbility2 = new FileAbility with LineNumberHandler with LineSplitterHandler val result = fileAbility2.handleFile(filename) result.foreach { ref => ref match { case s:String => println(s) case a:Array[Any] => for(e <- ref.asInstanceOf[Array[Any]]) {println(e)} case a:List[Any] => for(e <- ref.asInstanceOf[List[Any]]) {println(e)} case _ => println(ref) } } } }