Scala 的 class 层次结构设计。构造函数参数与成员

Design of Scala's class hierarchy. Constructor parameter vs member

我在为编译器项目设计 Scala 中的 class 层次结构时遇到问题。层次结构如下所示:

abstract class TACInstr(index:Int)

case class TAC_Label(label: String,index : Int) extends TACInstr(index)
case class TAC_Jump(label: TAC_Label,index : Int) extends TACInstr(index)
...

这里的index是一个变量,表示指令在某个列表中的序号。重要的是我不能声明这个变量至少对于 TAC_Label subclass 是不可变的,因为在我的代码中并不总是可以预测它在声明时应该是它的索引。

稍后我将在以下定义中使用此索引值:

  def getBlock(i : TACInstr) : BasicBlock = 
blocks.find(b => b.instr.index == i.index).get

所以基本上我是在比较不同指令的两个索引的相等性。这会产生以下错误:

Cannot resolve symbol index

因为显然以这种方式索引对于 classes 定义是私有的

我的做法

我尝试声明层次结构如下:

abstract class TACInstr(var index:Int)

case class TAC_Label(label: String,override var index : Int) extends TACInstr(index)
case class TAC_Jump(label: TAC_Label,override var index : Int) extends TACInstr(index)
...

但我收到以下错误类型:

Error:... overriding variable index in class TACInstr of type Int;
 variable index cannot override a mutable variable

这个问题有什么优雅的解决方案吗?有什么比宣布 index 为会员更好的事情?

主要问题是您试图覆盖一个字段。下面的例子解决了这个问题:

// index is public
abstract class TACInstr(var index:Int)

// label is public, i is private
class TAC_Label(val label: String, i: Int) extends TACInstr(i)
class TAC_Jump(val label: TAC_Label, i: Int) extends TACInstr(i)

val l = new TAC_Label("l", 0)
println(l.index)

现在有特征

trait TACInstr { var index:Int }

case class TAC_Label(label: String, var index: Int) extends TACInstr
case class TAC_Jump(label: TAC_Label, var index: Int) extends TACInstr

val l = TAC_Label("l", 0)
println(l.index)

更多scala方式

trait TACInstr { val index:Int }

// label is public, i is private
case class TACLabel(label: String, val index: Int) extends TACInstr
case class TACJump(label: TACLabel, val index: Int) extends TACInstr {
    def withLabelIndex(newIndex: Int): TACJump = this.copy(label = label.copy(index = newIndex))
}

val jump = TACJump(TACLabel("l", 1), 2)
val changed = jump.withLabelIndex(3)
println(changed)

这不是用scala写东西的方式。很多味道是:abstract class, var, parent fields。 scala 中的代码不是按照它的设计方式只会让它变得困难。