Scala 3与Scala 2.13同名内部trait混入差异问题咨询
Scala 3中同名内部Trait混入的兼容性变更问题
问题复现
以下代码在Scala 2.13可正常编译:
trait First { val first: Service trait Service { def someMethod(): Int } } trait LiveFirst extends First { override val first: Service = new Service { override def someMethod(): Int = 1 } } trait Second { val second: Service trait Service { def someMethod(): Int } } trait LiveSecond extends Second { override val second: Service = new Service { override def someMethod(): Int = 2 } } type Mixed = First with Second val mixed: Mixed = new LiveFirst with LiveSecond
但在Scala 3编译时会抛出错误:
[error] 32 |val mixed: Mixed = new LiveFirst with LiveSecond [error] | ^ [error] |error overriding trait Service in trait First; [error] | trait Service in trait Second cannot be used here - class definitions cannot be overridden
Scala 3的具体变更
Scala 2中,编译器会将不同父特质内的同名内部特质视为独立符号,混入时不会触发冲突检查。但Scala 3对嵌套类型的继承解析规则做了严格化调整:
当多个包含同名内部特质的父特质被混入到同一个类/实例中时,Scala 3会将这些内部特质解析为当前实例下的嵌套成员,认为Second.Service试图覆盖First.Service的定义。而Scala 3明确禁止类或特质定义被覆盖,因此抛出上述错误。
简单来说,Scala 3不再允许同一个类作用域中存在同名的嵌套特质/类定义,即使它们来自不同的父特质。
修复方案
可以通过明确指定路径依赖类型来区分不同的内部特质,避免编译器将它们视为同一成员:
修改LiveFirst和LiveSecond的实现,显式使用父特质的路径限定内部特质:
trait LiveFirst extends First { override val first: First.Service = new First.Service { override def someMethod(): Int = 1 } } trait LiveSecond extends Second { override val second: Second.Service = new Second.Service { override def someMethod(): Int = 2 } }
也可以直接修改其中一个内部特质的名称,从根源避免同名冲突。
内容的提问来源于stack exchange,提问作者Pavel
相关产品推荐
相关产品推荐

