【问题标题】:Messed up trait linearisation?搞砸了特征线性化?
【发布时间】:2012-06-23 18:46:54
【问题描述】:

这是一个让我头疼的特征线性化谜题。我基本上输入了Node,它定义了equalshashCode,以便与其他Nodes 进行比较。我有一个Selector 类型,它可以包装一个Node 以及额外的数据,因此有自己的equalshashCode 可以与其他Selectors 进行比较。

现在我有一个Standalone 类型,它结合了NodeSelector,但我得到不一致(?)关于equalshashCode 的线性化:

trait Selector { override def hashCode = 1 }
trait Event extends Selector

trait Node { override def hashCode = 2 }
trait Standalone extends Node with Event

当我从 EventStandalone 扩展时,现在一切都很好(调用了更具体的 hashCode 1):

object Single1 extends Event
Single1.hashCode // 1 -- ok

object Single2 extends Standalone
Single2.hashCode // 1 -- ok

如果我按这个顺序从两者扩展也很好:

object Compound1 extends Standalone with Event
Compound1.hashCode // 1 -- Ok

但是当我这样做时它搞砸了:

object Compound2 extends Event with Standalone
Compound2.hashCode  // 2 -- no!!!!!!!!

我做了一个小点图(mixin 从左到右排序):

所以,如果我正确理解了linearisation rules,我应该总是以Selector 实现的hashCode 结尾。这种行为的唯一解释是涉及某种贪婪/深度优先的事情......?

另外,如果我可以使用一种技术来确保无论何时混入Standalone,都可以确保Selector 优先于Node(除了从@987654350 复制equalshashCode @ to Standalone),非常感谢。

这是 Scala 2.9.2。

【问题讨论】:

    标签: scala multiple-inheritance traits linearization


    【解决方案1】:

    这种事情最好去规范。 该算法描述于5.1.2 Class Linearization

    解释它,类 C 的线性化是 C,然后是从最右边的项目开始扩展的事物的线性化。然后是线性化中删除重复项的最后一步,只保留最右边的。

    所以在你的例子中Compound1(忽略像 AnyRef 这样的内置插件):
    L(Compound1) = Compound1 + L(Event) + L(Standalone)
    L(Event) = Event + L(Selector)
    L(Selector) = Selector
    L(Standalone) = Standalone + L(Event) + L(Node)
    L(Node) = Node 放在一起:
    L(Compound1) = Compound1 Event Selector Standalone Event Selector Node
    删除重复项:
    Compound1 Standalone Event Selector Node

    对于Compound2,它最终是:
    Compound2 Standalone Node Event Selector


    至于另一个问题,我认为最简单的方法是覆盖Standalone 中的方法并在超类中调用所需的方法。

    trait Standalone extends Node with Event { override def hashCode = super[Event].hashCode }  
    

    假设这不是您所说的“复制”。

    【讨论】:

    • 只保留最右边的...好吧,这似乎就是问题所在。我想除了重新实现Standalone中的方法之外别无他法...
    • Standalone 在两个对象的线性化中位于 NodeSelector 之前,因此您可以在那里覆盖它。然而,这一切对我来说似乎很脆弱,你最好重新设计它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多