如何在Scala 3中重写获取宿主对象内单例对象的反射方法?
在Scala 3中实现按声明顺序收集单例对象的反射方法
实现代码
import scala.reflect.ClassTag import scala.reflect.runtime.universe.* def allSingletonObjects[A: ClassTag](host: Any): Vector[A] = { val mirror = runtimeMirror(host.getClass.getClassLoader) val classSymbol = mirror.classSymbol(host.getClass) classSymbol.info.declared .filter(_.isModule) .map { sym => mirror.reflectModule(sym.asModule).instance.asInstanceOf[A] } .toVector .reverse }
关键调整说明
- 替换
members为declared:Scala 3反射中members会包含所有继承来的成员,而declared仅返回当前对象自身声明的成员,精准匹配需求——只收集host对象内部定义的单例。 - 添加
ClassTag[A]上下文绑定:这是Scala 3中更规范的写法,能避免类型转换时的编译器警告,同时保证类型参数A的运行时信息可用。 - 保留
reverse操作:Scala反射的成员遍历顺序与代码声明顺序相反,和Scala 2的行为一致,反转后才能得到符合预期的声明顺序结果。
验证示例
使用题目中的Color定义测试:
sealed trait Color object Color { case object Red extends Color case object Green extends Color case object Blue extends Color } // 调用结果 allSingletonObjects[Color](Color) // 输出: Vector(Color.Red, Color.Green, Color.Blue)
注意事项
- 确保传入的
host是Scala对象(而非Java类),因为模块符号是Scala特有的反射概念。 - 题目明确所有目标单例均继承自
A,因此asInstanceOf[A]的类型转换是安全的。
内容的提问来源于stack exchange,提问作者kes
相关产品推荐
相关产品推荐

