Mixing “trait bundles”

只谈情不闲聊 提交于 2019-12-11 14:07:49

问题


I'm trying to make "trait bundles" that I can mix together, which mix traits contained within them. The following approach doesn't seem to work. Can you suggest an approach that can work?

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
}

This doesn't work, I think because there's nothing that says that BigNode and SmallNode extend NodesHaveHappiness.Node (but see this question). I don't want to write that in explicitly, though. I want to be able to put node types into separate "trait bundles" from "trait bundles" that define node attributes, and mix them together (somehow) so that all the node types get all the node attributes.

How do you keep this manageable in Scala?


回答1:


You are trying to intermix inheritance with composition in weird ways. The fact that you put a bunch of inner traits on a trait does not mean that inheriting the outer will make objects inherit the inner. Also, making Graph inherit some trait does nothing to the object you define inside Graph. You are instead saying that a Graph IS A Node, which is weird.

You probably want to build a class inheritance that makes sense to you, and then you have to "bundle" them together when you actually instantiate things. Here is a varied example:

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
  }
}


来源:https://stackoverflow.com/questions/33965799/mixing-trait-bundles

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!