在Scala中使用匿名类中的type参数

时间:2011-05-29 21:15:32

标签: scala

我正在尝试在匿名类中声明参数化类型的属性。这适用于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 个答案:

答案 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(结构类型采用相同方法的抽象类型)。