2

我在 Scala 2.10.3 中使用值类(扩展 AnyVal 的类),但是在将它们用作抽象方法的参数时遇到了一个奇怪的编译器错误。如以下示例所示:

class ValueClass(val x: Int) extends AnyVal

trait Test {
  def foo(v: ValueClass): Int
}

new Test {
  override def foo(v: ValueClass): Int = 1
}

编译器吐出以下错误:

error: bridge generated for member method foo: (v: ValueClass)Int in anonymous class $anon
which overrides method foo: (v: ValueClass)Int in trait Test
clashes with definition of the member itself;
both have erased type (v: Int)Int
          override def foo(v: ValueClass): Int = 1

为什么这不起作用?有没有办法将值类传递给抽象方法?

4

1 回答 1

2

因此,正如其他人所指出的,此问题已在以后的版本中得到修复。如果您对更改的内容感到好奇,我建议您查看此拉取请求

SI-6260 避免值类上的 lambdas 出现双重定义错误 当擦除的签名与覆盖方法的通用签名重叠时,将方法签名中的值类后擦除到底层类型会造成严重破坏。两者都没有空间。但我们真的需要两者;接口方法的调用者将传递桥需要拆箱的装箱值,并传递给接受未装箱值的特定方法。

这最常出现在值类中,这些值类被擦除为用作参数或匿名函数的返回类型的 Object。

这被认为是难以处理的,除非我们为子类中未装箱的特定方法选择不同的名称。但这听起来像是一项艰巨的任务,需要调用站点重写,也就是专业化。

但是有一个重要的特殊情况,我们不需要重写调用站点。如果定义方法的类是匿名的,其实就不需要拆箱的方法;它只会通过泛型方法调用。

在查看 Java 8 lambda 的处理方式时,我意识到了这一点。我期待桥接方法,但没有找到。lambda 主体直接放置在与通用签名完全匹配的方法中。

此提交检测到桥和目标之间的冲突,并通过修改目标方法符号的名称来恢复匿名类。这用作字节码名称。像以前一样,通用的桥接器具有必要的装箱/拆箱操作。

于 2014-07-23T14:17:01.563 回答