混入是特性常用的手段用来构建一个类
abstract class A { val message: String } class B extends A { val message = "I'm an instance of class B" } trait C extends A { def loudMessage = message.toUpperCase() } class D extends B with C val d = new D println(d.message) // I'm an instance of class B println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
类 D 有一个超类B 和一个混入特性C。类只能有一个超类但是可以有多个混入(分别使用 extends和with 关键字)。混入和超类拥有相同的超类型。
现在让我们看一个从抽象类开始的更有趣的示例:
abstract class AbsIterator { type T def hasNext: Boolean def next(): T }
这个类有一个抽象的类型 T,和一个标准的迭代器方法 。
然后我们将实现一个具体的类(所有的抽象成员包括 T,hasNext和 next 都将被实现)
class StringIterator(s: String) extends AbsIterator { type T = Char private var i = 0 def hasNext = i < s.length def next() = { val ch = s charAt i i += 1 ch } }
StringIterator 传递类一个 String ,并且可用于遍历字符串 (查看一个字符串是否包含某个字符)
现在,让我们创建一个也可以扩展的特征AbsIterator
。
trait RichIterator extends AbsIterator { def foreach(f: T => Unit): Unit = while (hasNext) f(next()) }
这个特性通过连续地在下个节点 ( next()) 调用 f:T => Unit 实现 foreach循环,只要还有下一个节点 (while(hasNext)) 还有。因为 RichIterator 是一个特性,所以它不需要实现 AbsIterator 的抽象成员。
我们更多的会用功能齐全的 StringIterator 类和 RichIterator 组合成一个单独的类
class RichStringIter extends StringIterator("Scala") with RichIterator val richStringIter = new RichStringIter richStringIter.foreach(println)
这个新类RichStringIter 有一个StringIterator 超类,以及一个 RichIterator 作为一个混合。
使用单继承,我们是无法做到这样的灵活性的。
【注:本章着重介绍的是特性的使用。特性可以声明抽象,又可以实现抽象。相当于java8中的接口,使用default 的方式override 抽象类的抽象方法】