Scala3中如何修复Observer trait匿名实例新增成员无法访问的问题
问题原因
Scala 3 调整了匿名子类的类型推断规则,和Scala 2的行为存在差异:
- Scala 2 会自动将匿名子类实例的类型推断为结构类型,自动包含你在匿名类中新增的
updated、isUpdated成员,因此可以直接访问。 - Scala 3 默认只会将匿名子类实例的类型推断为你显式声明的父类型,也就是你定义的
Observertrait,而该trait中没有定义updated成员,因此编译器会抛出成员不存在的错误。
修复方案
有三种常用的修复方式,按推荐度从高到低排列:
- 方案1:单独定义测试用的Observer实现类,避免使用匿名类
直接声明一个带测试所需成员的子类,实例化后类型明确,无需依赖结构类型:class TestObserver extends Observer { var updated: Boolean = false def isUpdated: Boolean = updated override def update: Unit = updated = true } // 测试代码中直接实例化 val observer = new TestObserver() - 方案2:显式声明变量的结构类型
如果你不想额外定义类,可以主动给observer变量声明完整的结构类型,告诉编译器该实例额外包含的成员:val observer: Observer { var updated: Boolean def isUpdated: Boolean } = new Observer { var updated: Boolean = false def isUpdated: Boolean = updated override def update: Unit = updated = true } - 方案3:开启Scala 2兼容的结构类型推断(不推荐)
在项目的编译参数中添加-language:reflectiveCalls,即可恢复Scala 2的自动结构类型推断行为。但该方案会带来反射调用的性能损耗,且类型安全性低,仅适合临时兼容老项目使用。
内容的提问来源于stack exchange,提问作者prolific-dev
相关产品推荐
相关产品推荐

