当某个特质被用于组合类时,被称为混入。

    1. abstract class A {
    2. val message: String
    3. }
    4. class B extends A {
    5. val message = "I'm an instance of class B"
    6. }
    7. trait C extends A {
    8. def loudMessage = message.toUpperCase()
    9. }
    10. class D extends B with C
    11. val d = new D
    12. println(d.message) // I'm an instance of class B
    13. println(d.loudMessage) // I'M AN INSTANCE OF CLASS B

    D有一个父类B和一个混入C。一个类只能有一个父类但是可以有多个混入(分别使用关键字extendwith)。混入和某个父类可能有相同的父类。

    现在,让我们看一个更有趣的例子,其中使用了抽象类:

    1. abstract class AbsIterator {
    2. type T
    3. def hasNext: Boolean
    4. def next(): T
    5. }

    该类中有一个抽象的类型T和标准的迭代器方法。

    接下来,我们将实现一个具体的类(所有的抽象成员ThasNextnext都会被实现):

    1. class StringIterator(s: String) extends AbsIterator {
    2. type T = Char
    3. private var i = 0
    4. def hasNext = i < s.length
    5. def next() = {
    6. val ch = s charAt i
    7. i += 1
    8. ch
    9. }
    10. }

    StringIterator带有一个String类型参数的构造器,可用于对字符串进行迭代。(例如查看一个字符串是否包含某个字符):

    现在我们创建一个特质,也继承于AbsIterator

    1. trait RichIterator extends AbsIterator {
    2. def foreach(f: T => Unit): Unit = while (hasNext) f(next())
    3. }

    该特质实现了foreach方法——只要还有元素可以迭代(while (hasNext)),就会一直对下个元素(next()) 调用传入的函数f: T => Unit。因为RichIterator是个特质,可以不必实现AbsIterator中的抽象成员。

    下面我们要把StringIteratorRichIterator 中的功能组合成一个类。

    1. object StringIteratorTest extends App {
    2. class RichStringIter extends StringIterator("Scala") with RichIterator
    3. val richStringIter = new RichStringIter
    4. richStringIter foreach println
    5. }

    新的类RichStringIter有一个父类StringIterator和一个混入RichIterator。如果是单一继承,我们将不会达到这样的灵活性。