0

我有以下代码:

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
}

错误说

在 Cell[Cell.this.NEXT] 类型的特征 CellT 中覆盖变量 next;变量 next 具有不兼容的类型

很明显,this它将具有与VAL <: AnyVal相同的类型NEXT <: AnyVal,但是,我仍然得到错误。我如何告诉 Scalanext应该能够返回任何类型Cell[A <: AnyVal],但这种类型应该与类类型参数相同[VAL <: AnyVal]???否则我可以使用[VAL],但它会限制太多,例如因为Cell[Int]它会限制next方法只返回Cell[Int]类型实例。但我希望next可以重新分配给任何其他Cell[*]类型的实例。

4

3 回答 3

2

如果您想next重新分配给任何其他 Cell[*] 类型实例,您可以使用存在类型

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,this)
单元格(1,this)
单元格(1,Cell(false,this))
单元格(false,this)
单元格(1,Cell(true,this))
单元格(true,this)

于 2012-09-13T17:19:18.383 回答
1

很明显,这将具有类型 VAL <: AnyVal 与 NEXT <: AnyVal 相同

不,它们不一样,它们只是共享相同的约束。NEXT 尚未指定。想象一下,您随后像这样子类化 Cell:

class StringNextCell extends Cell {
    type NEXT = String
}

现在,StringNextCell.next应该是类型Cell[String],但您来自 Cell 的声明将其声明为Cell[Int]

于 2012-09-13T17:39:42.213 回答
1

这与其说是一个警告,不如说是一个答案。一个月前我写了非常相似的代码,我花了很多次迭代才知道当谈到 Scala 类型时,越粗越好。

请记住,Scala 类型参数检查仅在编译时进行,因此它通常比您想象的要粗略。花 15 分钟编译您的代码,却发现您的 X[Foo <: Bar] 被视为 X[_],这真的很烦人。

我建议您从以下内容开始:

abstract class Cell[VAL] {
    var value: VAL
    var next: Cell[_]
}

并且只有在您有迫切需要时才能更具体。很有可能,如果您需要知道 next 的类型,无论如何您都需要进行明确的运行时检查。

于 2012-09-13T17:45:53.177 回答