我有以下代码:
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
}
错误说
在trait CellT类型中覆盖下一个变量 细胞[Cell.this.NEXT];变量接下来有 不兼容的类型
很明显this
的{{1}}类型与VAL <: AnyVal
相同,但我仍然会收到错误。如何告诉Scala NEXT <: AnyVal
应该能够返回next
类型的任何内容,但是此类型不必须与类类型参数{{1}相同} ...否则我可以使用Cell[A <: AnyVal]
,但限制性太强,例如对于[VAL <: AnyVal]
,它会限制[VAL]
方法仅返回Cell[Int]
类型实例。但我希望next
可以重新分配给任何其他Cell[Int]
类型的实例。
答案 0 :(得分:2)
如果您希望next
可以重新分配给任何其他Cell [*]类型实例,则可以使用existential types:
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,细胞(假的,这一点))
细胞(假的,这一点)
细胞(1,细胞(真,此))
细胞(真,此)
答案 1 :(得分:1)
这里很明显,它的类型为VAL&lt ;: AnyVal,与NEXT&lt ;: AnyVal
相同
不,它们不一样,它们只是共享相同的约束。 NEXT尚未指定。想象一下,你随后将Cell子类化为:
class StringNextCell extends Cell {
type NEXT = String
}
现在,StringNextCell.next
应该是Cell[String]
类型,但是来自Cell的声明声明为Cell[Int]
答案 2 :(得分:1)
这不是一个警告的答案。我在一个月前编写了非常相似的代码,我花了很多次迭代才知道在Scala打字方面,更粗糙更好。
请记住,Scala类型参数检查仅限编译时,因此它通常比您想象的更粗糙。花15分钟来编译代码真的很烦人,只是发现你的X [Foo&lt ;: Bar]被视为X [_]。
我建议您先从:
开始abstract class Cell[VAL] {
var value: VAL
var next: Cell[_]
}
只有在迫切需要时才会更具体。如果你需要知道下一个的类型,你可能需要进行明确的运行时检查。