You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:22:50