Scala trait mixin中方法调用的顺序
我的程序结构如下:
abstract class IntQueue { def get(): Int def put(x: Int) } trait Doubling extends IntQueue{ abstract override def put(x: Int) { println("In Doubling's put") super.put(2*x) } } trait Incrementing extends IntQueue { abstract override def put(x: Int) { println("In Incrementing's put") super.put(x + 1) } } class BasicIntQueue extends IntQueue { private val buf = new ArrayBuffer[Int] def get() = buf.remove(0) def put(x: Int) { println("In BasicIntQueue's put") buf += x } } 当我做: val incrThendoublingQueue = new BasicIntQueue with Doubling with Incrementing incrThendoublingQueue.put(10) println(incrThendoublingQueue.get()) 输出是:
我在这里订购时有点困惑.我对这种情况的线性化顺序的理解是:
所以当我调用put时,不应该首先调用BasicIntQueue的版本吗? 解决方法
不.这种情况下的线性化是
{<anonymous-local>,Incrementing,Doubling,BasicIntQueue,IntQueue,AnyRef,Any} 您可以: >只需阅读规范并说服自己必须如此 阅读规范 section 5.1.2 of the Spec 如果应用正确的公式,则会为所涉及的特征和基类获得以下线性化: IntQueue : {IntQueue,Any} Doubling : {Doubling,Any} Incrementing : {Incrementing,Any} BasicIntQueue : {BasicIntQueue,Any} 如果你最后结合这些线性化来计算被实例化为incrThendoublingQueue的匿名本地类的线性化: <anonymous-local-class>,L(Incrementing) + L(Doubling) + L(BasicInt) 你获得了上面已经显示的线性化.因此,应按此顺序调用方法: >递增 这与实际输出一致. 重新实现线性化算法以获得乐趣 这实际上是规范中无依赖性的片段之一,您可以从头开始轻松实现.该 implicit class ConcatenationWithReplacementOps[A](list: List[A]) { def +^->(other: List[A]): List[A] = list match { case Nil => other case h :: t => if (other contains h) (t +^-> other) else h :: (t +^-> other) } } 建模类声明C扩展C1与… Cn也是 case class ClassDecl(c: String,extendsTemplate: List[ClassDecl]) { def linearization: List[String] = c :: ( extendsTemplate .reverse .map(_.linearization) .foldLeft(List.empty[String])(_ +^-> _) ) } 线性化的公式在此实现为方法.注意反过来. 规范中给出的例子: val any = ClassDecl("Any",Nil) val anyRef = ClassDecl("AnyRef",List(any)) val absIterator = ClassDecl("AbsIterator",List(anyRef)) val richIterator = ClassDecl("RichIterator",List(absIterator)) val stringIterator = ClassDecl("StringIterator",List(absIterator)) val iter = ClassDecl("Iter",List(stringIterator,richIterator)) println(iter.linearization.mkString("{",","}")) 完全按照规范生成输出: {Iter,RichIterator,StringIterator,AbsIterator,Any} 现在,这是您的示例的模型: val intQueue = ClassDecl("IntQueue",List(anyRef)) val doubling = ClassDecl("Doubling",List(intQueue)) val incrementing = ClassDecl("Incrementing",List(intQueue)) val basicQueue = ClassDecl("BasicIntQueue",List(intQueue)) val incrThendoublingQueue = ClassDecl( "<anonymous-local>",List(basicQueue,doubling,incrementing) ) println(incrThendoublingQueue.linearization.mkString("{","}")) 它产生了我上面已经显示的线性化顺序: {<anonymous-local>,Any} 一切似乎都按预期工作,没有理由写入Scala-Users. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |