Использование параметра типа в анонимном классе в Scala - PullRequest
3 голосов
/ 30 мая 2011

Я пытаюсь объявить атрибут параметризованного типа внутри анонимного класса.Это работает в 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)
}

Итак, вопрос: почему компилятор не может сделать это для меня?

Ответы [ 3 ]

1 голос
/ 10 июня 2011

Добавляя открытую переменную в свой итератор, вы создаете структурный тип, который является подтипом Iterator. Это будет работать, если вы измените i на приватную переменную.

1 голос
/ 06 июня 2014

Быстрое исправление состоит в том, чтобы избежать структурного возвращаемого типа:

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 является структурным типомform Iterator[T] with Object {def next: T; var i : T; def hasNext: Boolean} (как может предложить IDE, например IntelliJ).

Таким образом, вы определяете метод, тип возвращаемого значения которого является структурным типом, который использует абстрактный тип этого же метода.Это то, что беспокоит скаляк (структурный тип с абстрактным типом того же метода).

1 голос
/ 30 мая 2011

Я, к сожалению, не уверен, почему это не работает.Но вот альтернативный обходной путь, который избегает приведений:

def it[T <: AnyRef](x: T) = {
  class Forever extends Iterator[T] {
    var i = x
    def next = i
    def hasNext = true
  }
  new Forever
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...