2

我是 Scala 的新手。如何在类中实现方法?

我已经定义了一个看起来像这样的特征:

trait Node extends Component{
  val label:Int
  val inputEdges:List[Edge] = List[Edge]()
  val outputEdges:List[Edge] = List[Edge]()

  def addInputEdge(edge:Edge) = {
    inputEdges :+ edge
    this
  }

  def addOutputEdge(edge:Edge) = {
    outputEdges :+ edge
    this
  }
}

case class SomeNode(label:Int) extends Node

我需要帮助来了解如何实现这两种方法。

每个扩展 Node 的类都必须在构造函数中提供一个标签,但应该继承这两个方法和两个列表。此外,这些方法应返回节点的新对象,并将边缘添加到列表之一。现在,如果我调用其中一种方法,我会得到相同的对象,但没有将边缘添加到列表之一。这是有道理的,但是当两个列表不可变时,我不知道如何添加边。

我真的不想在构造函数中传递列表,因为那样我会得到带有许多参数的构造函数。

4

3 回答 3

0

你可以只使用可变变量。不好...重新考虑使用具有长构造函数的案例类。

干得好:

trait Node extends Component{
  var label:Int
  var inputEdges:List[Edge] = List[Edge]()
  var outputEdges:List[Edge] = List[Edge]()

  def addInputEdge(edge:Edge) = {
    inputEdges :+= edge
    this
  }

  def addOutputEdge(edge:Edge) = {
    outputEdges:+=  edge
    this
  }
}

case class SomeNode(label:Int) extends Node
于 2013-05-15T22:56:06.860 回答
0

有几种方法可以完成您的要求。首先,您可以简单地将 inputEdges 和 outputEdges 定义为vars 而不是vals。这样,您可以将您在 addInputEdge 和 addOutputEdge 方法中创建的列表重新分配给相应的字段。

trait Node extends Component {
  val label:Int
  var inputEdges:List[Edge] = List[Edge]()
  var outputEdges:List[Edge] = List[Edge]()

  def addInputEdge(edge:Edge) = {
    inputEdges = inputEdges :+ edge
    this
  }

  def addOutputEdge(edge:Edge) = {
    outputEdges = outputEdges :+ edge
    this
  }
}

然而,这引入了一个可能不受欢迎的可变状态。类似的替代方法是使用可变列表,例如MutableList。另一种方法是使添加方法抽象化,并让子类负责通过添加给定的边来创建它们自己的新实例。

于 2013-05-15T17:24:49.133 回答
0

我知道您要求的解决方案是列表不出现在构造函数中,但是如果您使用默认参数,希望它是可以接受的。(我很感兴趣为什么要避免“胖”构造函数,默认参数或伴随对象 apply 方法可以在这里提供帮助。)
(顺便说一句:def在特征中使用抽象事物而Seq不是List

这是我的方法:

trait Self[S] { self: S =>
  type SELF = S
}

trait Component
trait Edge

trait Node extends Component {
  type SELF
  protected def constructor: (Int, Seq[Edge], Seq[Edge]) => SELF
  def label: Int
  def inputEdges: Seq[Edge]
  def outputEdges: Seq[Edge]
  private def clone(inputEdges: Seq[Edge] = this.inputEdges, outputEdges: Seq[Edge] = this.outputEdges) = constructor(label, inputEdges, outputEdges)
  final def addInputEdge(edge: Edge) = clone(inputEdges = inputEdges :+ edge)
  final def addOutputEdge(edge: Edge) = clone(outputEdges = outputEdges :+ edge)
}

case class SomeNode(label: Int, inputEdges: Seq[Edge] = Seq(), outputEdges: Seq[Edge] = Seq()) extends Node with Self[SomeNode] {
  def constructor = SomeNode
}

val node1 = SomeNode(1)
val node2: SomeNode = node1.addInputEdge(new Edge {})
于 2013-05-15T14:13:07.873 回答