混合“特质包”

时间:2015-11-27 23:03:43

标签: scala mixins

我正在努力制作“特质束”,我可以将它们混合在一起,混合其中包含的特征。以下方法似乎不起作用。你能建议一种可行的方法吗?

trait GraphTypes {
  trait Node {
    def size: Double
  }
}

trait HasBigAndSmallNodes extends GraphTypes {
  trait BigNode extends super.Node {
    override def size = 5.00
  }

  trait SmallNode extends super.Node {
    override def size = 0.05
  }
}

trait NodesHaveHappiness extends GraphTypes {
  trait Node extends super.Node {
    def happiness = size * 2.0  // Ideally, .happiness would mix in
  }                             // to BigNode and SmallNode.
}

object ACertainGraph extends GraphTypes
  with NodesHaveHappiness with HasBigAndSmallNodes
{
  val big = new BigNode { }
  val small = new SmallNode { }

  println(big.happiness)  // error: value happiness is not a member of Graph.BigNode
}

这不起作用,我认为因为没有任何内容表明BigNodeSmallNode延伸NodesHaveHappiness.Node(但请参阅this question)。不过,我不想明确地写出来。我希望能够将节点类型放入定义节点属性的“特征包”中的单独“特征包”中,并将它们混合在一起(以某种方式),以便所有节点类型都获得所有节点属性。

如何在Scala中保持这种可管理性?

1 个答案:

答案 0 :(得分:0)

您正试图以奇怪的方式将继承与组合混合在一起。你在一个特征上放置一堆内部特征的事实并不意味着继承外部会使对象继承内部特征。此外,使Graph继承某些特征对Graph中定义的对象不起作用。你反而说是一个Graph 是一个节点,这很奇怪。

您可能希望构建一个对您有意义的类继承,然后您必须"捆绑"当你实际实例化它们时它们在一起。这是一个多变的例子:

trait Node

class SizedNode(val size: Double)

trait HappyNode extends SizedNode { // Here you specify that a happy node requires a size, so happines is well defined.
  def happiness = size * 2.0
}

trait SmartNode extends Node {
  def saySomethingSmart() = println("E = mc^2")
}

object Graph {
  def createBigNode() = new SizedNode(5.0) with HappyNode with SmartNode  // Here you can "bundle" as many traits as you want.
  def createSmallNode() = new SizedNode(0.05) with HappyNode
}

object Test {

  def main(args: Array[String]) {

    println(Graph.createBigNode().happiness)  // 10.0
    println(Graph.createSmallNode.happiness)  // 0.1
    Graph.createBigNode().saySomethingSmart() // E = mc^2
  }
}