2011-05-29 59 views
3

我试图在匿名类中声明参数化类型的属性。这部作品在Java中,斯卡拉(2.9),但我得到的编译错误:在Scala中的匿名类中使用类型参数

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) 
} 

所以问题是:为什么编译器不能为我做?

+3

通过向您的迭代器添加公共变量,您可以创建一个结构类型,它是Iterator的子类型。如果您将我更改为一个私有变量,它将起作用。 – 2011-05-29 21:59:02

+0

事实上,我不知道我怎么会错过这样一个明显的解决方案。 – 2011-05-29 23:54:35

+0

@Kris:请回答以下答案,以便我可以正确接受它。 – 2011-05-29 23:55:44

回答

1

通过增加公共变量到你的迭代器,您可以创建一个结构类型,它是迭代的子类型。如果您将我更改为一个私有变量,它将起作用。

1

我很遗憾,不知道为什么这不起作用。但这里是避免石膏替代的解决方法:

def it[T <: AnyRef](x: T) = { 
    class Forever extends Iterator[T] { 
    var i = x 
    def next = i 
    def hasNext = true 
    } 
    new Forever 
} 
+0

这是可行的,因为它避免了上面提到的结构类型。 – 2011-05-29 21:59:48

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) 
} 

事实上,在对象DemoFail方法it没有一个明确的返回类型。因此,这种返回类型是由编译器推断的。

在此,作为要覆盖现有成员和添加新的一至Iterator[T],该方法it的推断返回类型是结构类型的形式Iterator[T] with Object {def next: T; var i : T; def hasNext: Boolean}(如像的IntelliJ一个IDE可以建议)的。

因此,您正在定义一种方法,其返回类型是使用此方法的抽象类型的结构类型。这是什么困扰scalac(具有相同方法的抽象类型的结构类型)。