我有以下代码:
trait CellT[VAL <: AnyVal] {
var value: VAL
type NEXT <: AnyVal
var next: CellT[NEXT]
}
abstract class Cell[VAL <: AnyVal] extends CellT[VAL] {
var next = this // defaults to `this`. ERROR
}
// impl example:
class CellInt extends Cell[Int] {
var value: Int = 0
}错误上说
在CellT类型的CellCell.this.NEXT中重写变量next;变量next具有不兼容的类型
显然,this的VAL <: AnyVal类型与NEXT <: AnyVal类型相同,但是,我仍然会得到错误。我如何告诉Scala next应该能够返回任何类型的Cell[A <: AnyVal],但是这种类型不应该与类类型参数[VAL <: AnyVal]相同?否则,我可以只使用[VAL],但它将限制太大,例如,对于Cell[Int],它将限制next方法只返回Cell[Int]类型实例。但是我希望next可以重新分配到任何其他Cell[*]类型的实例中。
发布于 2012-09-13 17:19:18
如果希望将next重命名为任何其他单元格*类型实例,则可以使用存在类型
trait CellT[VAL <: AnyVal] {
var value: VAL
var next: CellT[_ <: AnyVal]
}
abstract class Cell[VAL <: AnyVal] extends CellT[VAL] {
var next: CellT[_ <: AnyVal] = this // defaults to `this`
override def toString = "Cell(%s,%s)".format(value, if(next == this) "this" else next.toString)
}
// impl example:
class CellInt extends Cell[Int] {
var value: Int = 0
}
class CellBoolean extends Cell[Boolean] {
var value = false
}
var c1 = new CellInt
var c2 = new CellBoolean
println(c1)
c1.value = 1
println(c1)
c1.next = c2
println(c1)
println(c2)
c2.value = true
println(c1)
println(c2)输出:
单元格(0,这个)
单元格(1,这个)
单元格(1,Cell(false,this))
单元格(假,此)
单元格(1,单元格(对,此))
单元格(对,这个)
发布于 2012-09-13 17:39:42
这里很明显,它的类型为VAL <:AnyVal,与NEXT <:AnyVal相同
不,他们不是一样的,他们只是有着同样的约束。NEXT尚未指定。假设您随后像下面这样的子类Cell:
class StringNextCell extends Cell {
type NEXT = String
}现在,StringNextCell.next应该是Cell[String]类型的,但是您从单元格中的声明将它声明为Cell[Int]
发布于 2012-09-13 17:45:53
这与其说是一个答案,不如说是一个警告。一个月前,我编写了非常类似的代码,我花了很多迭代才了解到,当使用Scala类型时,更粗的代码更好。
请记住,Scala类型参数检查仅限于编译时,因此它通常比您想象的要粗。花15分钟让您的代码编译非常烦人,结果却发现您的XFoo <:Bar被视为X_。
我建议你从以下几个方面着手:
abstract class Cell[VAL] {
var value: VAL
var next: Cell[_]
}只有在你有迫切需要的时候才能说得更具体些。很可能,如果您需要知道next的类型,那么无论如何都需要进行显式的运行时检查。
https://stackoverflow.com/questions/12410669
复制相似问题