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 中的代码不是按照它的设计方式只会让它变得困难。
我在为编译器项目设计 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 中的代码不是按照它的设计方式只会让它变得困难。