Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala类中实现可变方法_Scala_Constructor_Functional Programming_Immutability - Fatal编程技术网

在Scala类中实现可变方法

在Scala类中实现可变方法,scala,constructor,functional-programming,immutability,Scala,Constructor,Functional Programming,Immutability,我是斯卡拉的新手。如何在类中实现方法 我定义了一个如下所示的特征: 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 addOu

我是斯卡拉的新手。如何在类中实现方法

我定义了一个如下所示的特征:

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
我需要帮助了解如何实现这两种方法

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


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

我知道您要求的解决方案中列表不出现在构造函数中,但如果您使用默认参数,则希望可以接受。(我很感兴趣的是,为什么要避免使用“胖”构造函数、默认参数或伴随对象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 {})

有几种方法可以满足你的要求。首先,您可以简单地将输入和输出定义为
var
s,而不是
val
s。这样,您就可以将AddInputGe和AddOutputGe方法中创建的列表重新分配到相应的字段中

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

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

您可以只使用可变变量。不好。。。 重新考虑使用长构造函数的用例类

给你:

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

谢谢,不过这似乎比拥有一个大的构造函数(对我来说是最复杂的)更让人困惑。我不喜欢大的构造函数,因为在我看来,他们很难理解类到底是什么。我只是在寻找一个简单而优雅的方法解决方案,在OOP语言中是可变的。