给定的代码接受一个类型,接受它已知的直接子类,过滤属于Case类的子类,然后接受该Case类的同伴:
def firstSubclassWithCompanion[T: TypeTag]: String = {
val superclass = implicitly[TypeTag[T]].tpe.typeSymbol.asClass
val caseClass = superclass.knownDirectSubclasses.map(_.asClass).filter(_.isCaseClass).head
s"case class $caseClass has companion ${caseClass.companion}"
}
举一个简单的例子
sealed trait With
case class WithCase() extends With
它给出了预期收益
> firstSubclassWithCompanion[With]
"class WithCase has companion object WithCase"
因为With
特征有一个WithCase
子类,这个子类是Case类,它有一个伴随对象(由编译器定义)。
但是,在下面的示例中,子类是在继承特征的伴随对象中定义的:
sealed trait Without
object Without {
case class WithoutCase() extends Without
}
它不返回伴随对象
> firstSubclassWithCompanion[Without]
"class WithoutCase has companion <none>"
如果在其他对象中定义它,则可以很好地工作。
1条答案
按热度按时间sczxawaw1#
错误应在https://github.com/scala/bug/issues报告
解决方法是使用
caseClass.owner.typeSignature.decl(caseClass.name)
而不是caseClass.companion
。另一种解决方法是将此运行时反射代码转换为宏(编译时反射)。因为这里的所有类都是在编译时定义的,所以使用宏是有意义的。