Using a type parameter in an anonymous class in Scala

I am trying to declare an attribute of a parameterized type inside an anonymous class. This works in Java, in Scala (2.9), however I get a compilation error:

Parameter type in structural refinement may not refer to an abstract type defined outside that refinement

This is the code:

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

I can make it work by manually deleting types:

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

So the question is: why can't the compiler do this for me?

+3
source share
3 answers

By adding a public variable to your iterator, you will create a structural type that is a subtype of Iterator. It will work if you change me to a private variable.

+1
source

Unfortunately, I do not know why this does not work. But there is an alternative workaround here that avoids throws:

def it[T <: AnyRef](x: T) = {
  class Forever extends Iterator[T] {
    var i = x
    def next = i
    def hasNext = true
  }
  new Forever
}
+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)
}

Indeed, a method iton an object DemoFaildoes not have an explicit return type. Therefore, this type of return is deduced by the compiler.

Here, since you are redefining existing elements and adding a new one to Iterator[T], the return type of the return method itis the structural type of the form Iterator[T] with Object {def next: T; var i : T; def hasNext: Boolean}(as an IDE might seem, like IntelliJ),

Thus, you define a method whose return type is a structural type that uses the abstract type of the same method. This is what worries the scalp (a structural type with the same abstract type method).

+1
source

All Articles