Scala 2.11.11下MongoDB驱动ADT编解码器编译失败求助
解决Scala 2.11下MongoDB驱动ADT Codec编译错误的问题
这个错误是Scala 2.11和2.12宏系统的行为差异导致的。Mongo Scala Driver的Macros.createCodecProvider宏在Scala 2.11环境下,要求sealed类的所有子类必须先被编译器完全处理,才能生成对应的Codec;而Scala 2.12对宏系统做了优化,自动兼容了父类在前、子类在后的定义顺序。
针对你的场景,有两种简单可行的解决方案:
方案一:延迟Codec初始化(推荐)
把Codec和CodecRegistry的定义改为lazy val,让编译器延迟到首次使用它们时再执行宏解析,这时所有子类已经被正确加载完成:
import org.mongodb.scala.bson.codecs.{DEFAULT_CODEC_REGISTRY, Macros} import org.bson.codecs.configuration.CodecRegistries.{fromProviders, fromRegistries} object Models { sealed class Tree case class Branch(b1: Tree, b2: Tree, value: Int) extends Tree case class Leaf(value: Int) extends Tree // 用lazy val延迟宏的执行时机 lazy val treeCodec = Macros.createCodecProvider[Tree]() lazy val treeCodecRegistry = fromRegistries( fromProviders(treeCodec), DEFAULT_CODEC_REGISTRY ) }
方案二:将Codec定义放在嵌套对象中
把Codec相关代码放到一个嵌套的object里,利用Scala的编译顺序(先处理外部类的所有成员,再处理嵌套对象),确保子类在宏执行前已经完成定义:
import org.mongodb.scala.bson.codecs.{DEFAULT_CODEC_REGISTRY, Macros} import org.bson.codecs.configuration.CodecRegistries.{fromProviders, fromRegistries} object Models { sealed class Tree case class Branch(b1: Tree, b2: Tree, value: Int) extends Tree case class Leaf(value: Int) extends Tree // 嵌套对象会在外部类所有成员处理完成后编译 object Codecs { val treeCodec = Macros.createCodecProvider[Tree]() val treeCodecRegistry = fromRegistries( fromProviders(treeCodec), DEFAULT_CODEC_REGISTRY ) } } // 使用时通过 Models.Codecs.treeCodecRegistry 访问
为什么Scala 2.12下正常?
Scala 2.12改进了宏系统对sealed类的处理逻辑,能够自动识别同一编译单元内的子类,不需要额外调整初始化时机,所以你的原始代码在2.12环境下可以直接编译通过。
内容的提问来源于stack exchange,提问作者alifirat
相关产品推荐
相关产品推荐

