2011-05-29 90 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(具有相同方法的抽象類型的結構類型)。