7.4 Trait方法的延迟绑定
上面的例子里,Check
类的check()
方法是具体的,trait都是从这个类继承来的。我们见识到了,在trait里对super.check()
的调用是如何绑定到其左边的trait或是其混入的类的。但如果基类的方法是抽象的,就会变得有点复杂。下面进一步探索一番。
先写一个抽象类Writer
,它有一个抽象方法writeMessage()
:
TraitsAndTypeConversions/MethodBinding.scala
abstract class Writer {
def writeMessage(message: String)
}
任何继承这个类的类都要实现writeMessage()
方法。如果有一个trait继承了这个抽象类,并且用super
调用了这个抽象方法,Scala会要求将方法声明为abstract override
。将这两个关键字组合到一起看上去有些奇怪。关键字override
告诉Scala,要为基类的一个已知方法提供一个实现。同时,还表示,这个方法实际最后的“终极”实现由混入这个trait的类提供。下面是一个例子,这个trait继承了上面的那个类:
TraitsAndTypeConversions/MethodBinding.scala
trait UpperCaseWriter extends Writer {
abstract override def writeMessage(message: String) =
super.writeMessage(message.toUpperCase)
}
trait ProfanityFilteredWriter extends Writer {
abstract override def writeMessage(message: String) =
super.writeMessage(message.replace("stupid", "s-----"))
}
在这段代码里,为了调用super.writeMessage
,Scala做了两件事。首先,它对这个调用进行了延迟绑定。其次,它会要求混入这些trait的类提供该方法的实现。ProfanityFilteredWriter
只负责处理有些粗鲁的单词——且仅当它以小写形式出现。这是为了体现混入的顺序。
现在来用一下这些trait。先来写一个类StringWriterDelegate
,继承自抽象类Writer
,将写消息的操作委托给一个StringWriter
实例:
TraitsAndTypeConversions/MethodBinding.scala
class StringWriterDelegate extends Writer {
val writer = new java.io.StringWriter
def writeMessage(message: String) = writer.write(message)
override def toString() : String = writer.toString
}
在上面StringWriterDelegate
的定义里可以混入一个或多个trait,不过,在这里,我们选择的是在创建这个类的实例时混入trait。
TraitsAndTypeConversions/MethodBinding.scala
val myWriterProfanityFirst =
new StringWriterDelegate with UpperCaseWriter with ProfanityFilteredWriter
val myWriterProfanityLast =
new StringWriterDelegate with ProfanityFilteredWriter with UpperCaseWriter
myWriterProfanityFirst writeMessage "There is no sin except stupidity"
myWriterProfanityLast writeMessage "There is no sin except stupidity"
println(myWriterProfanityFirst)
println(myWriterProfanityLast)
在第一个语句里,ProfanityFilteredWriter
是最右的trait,所以,它会先起作用。然而,在第二个语句中,它会后起作用。这段代码可能需要花些时间研究一下。这两个实例的方法执行顺序如图7-1所示:
图7-1 两个实例的方法执行顺序
输出如下:
THERE IS NO SIN EXCEPT S-----ITY
THERE IS NO SIN EXCEPT STUPIDITY