我正在尝试在匿名类中声明参数化类型的属性。这适用于Java,在Scala(2.9)中但是我得到了编译错误:
Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
这是代码:
object DemoFail extends App {
def it[T <: AnyRef](x: T) = new Iterator[T] {
var i = x // here is the error
def next = i
def hasNext = true
}
for (i ← it(int2Integer(4))) println(i)
}
我可以通过手动“删除”类型来实现它:
object DemoOK extends App {
def it[T <: AnyRef](x: T) = new Iterator[T] {
var i: AnyRef = x
def next = i.asInstanceOf[T]
def hasNext = true
}
for (i ← it(int2Integer(4))) println(i)
}
所以问题是:为什么编译器不能为我做这件事?
答案 0 :(得分:1)
不幸的是,我不确定为什么这不起作用。但这是一个避免强制转换的替代解决方法:
def it[T <: AnyRef](x: T) = {
class Forever extends Iterator[T] {
var i = x
def next = i
def hasNext = true
}
new Forever
}
答案 1 :(得分:1)
通过向迭代器添加公共变量,可以创建一个结构类型,它是Iterator的子类型。如果你将i改为私有变量,它将起作用。
答案 2 :(得分:1)
快速解决方法是避免结构返回类型:
object DemoFail extends App {
// The same with an explicit (non structural) return type
// vvvvvvvvvvvvv
def it[T <: AnyRef](x: T): Iterator[T] =
new Iterator[T] {
var i = x // no more error
def next = i
def hasNext = true
}
for (i ← it(int2Integer(4))) println(i)
}
实际上,对象it
上的方法DemoFail
没有明确的返回类型。因此,这种返回类型是由编译器推断的。
在此,当您覆盖现有成员并向Iterator[T]
添加新成员时,方法it
的推断返回类型是Iterator[T] with Object {def next: T; var i : T; def hasNext: Boolean}
形式的结构类型(作为像IntelliJ这样的IDE可以建议)。
因此,您定义的方法的返回类型是使用此相同方法的抽象类型的结构类型。这就是困扰scalac(结构类型采用相同方法的抽象类型)。