Scala - 相同但不同的类型

时间:2012-09-13 16:22:48

标签: scala inheritance types

我有以下代码:

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]类型的实例。

3 个答案:

答案 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[_]
}

只有在迫切需要时才会更具体。如果你需要知道下一个的类型,你可能需要进行明确的运行时检查。