我是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的类都必须在构造函数中提供标签,但是应该继承这两个方法和两个列表。此外,这些方法应返回节点的新对象,并将边添加到其中一个列表中。现在,如果我调用其中一个方法,我会获得相同的对象,而没有边缘添加到列表中的一个。这是有道理的,但我不知道如何在两个列表不可变时添加边缘。
我真的不想在构造函数中传递列表,因为我将获得具有许多参数的构造函数。
答案 0 :(得分:0)
我知道你要求一个解决方案,其中列表没有出现在构造函数中,但是如果你使用默认参数,那么希望是可以接受的。 (我感兴趣的是你为什么要避免“胖”构造函数,默认参数或伴随对象的应用方法可以在这里帮助。)
(顺便说一句:在抽象事物的特征中使用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 {})
答案 1 :(得分:0)
有几种方法可以满足您的要求。首先,您可以简单地将inputEdges和outputEdges定义为var
s而不是val
s。这样,您可以将在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。另一个方法是使添加metdos抽象,并让子类负责通过添加给定边创建自己的新实例。
答案 2 :(得分:0)
你可以使用可变变量。不太好... 重新考虑使用带有长构造函数的case类。
你走了:
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