Scala2与Scala3匿名子类额外方法差异:编译报错咨询
Scala2与Scala3匿名子类类型推断差异问题解析
问题代码
object Main { def main(args:Array[String]): Unit = { val foo = new Foo(7) println(foo.double) // 14 val bar = new Foo(8) { def triple:Int = this.i * 3 } println(bar.double) // 16 println(bar.triple) // 24 in scala2; compile error in scala3 } } class Foo(val i:Int) { def double:Int = i*2 }
编译错误(Scala3)
-- [E008] Not Found Error: /tmp/example.scala:12:20 ---- 12 | println(bar.triple) | ^^^^^^^^^^ | value triple is not a member of Foo
原因解析
Scala2和Scala3在匿名子类实例的类型推断逻辑上存在核心差异:
- Scala2中,编译器会自动将
bar的类型推断为该匿名子类的结构类型,因此能识别到类体中新增的triple方法。 - Scala3对类型推断做了保守性调整,默认将此类实例的类型推断为父类
Foo。由于父类Foo未定义triple方法,直接调用就会触发编译错误。
解决办法
有三种可行方式让Scala3识别到triple方法:
- 显式声明结构类型:给
bar指定包含triple方法的结构类型,明确告知编译器新增方法的存在:val bar: Foo { def triple: Int } = new Foo(8) { def triple:Int = this.i * 3 } - 强制类型转换:在实例化后显式将匿名子类转换为对应结构类型:
val bar = new Foo(8) { def triple:Int = this.i * 3 }.asInstanceOf[Foo { def triple: Int }] - 定义显式子类:如果这类场景需要复用,直接定义继承自
Foo的子类,彻底规避匿名子类的类型推断问题:class FooWithTriple(i: Int) extends Foo(i) { def triple: Int = i * 3 } val bar = new FooWithTriple(8)
内容的提问来源于stack exchange,提问作者bwbecker
相关产品推荐
相关产品推荐

