我想利用Scala反射来隐式传递ClassTag。
关于如何实现这一点,StackOverflow上有很多解决方案。
import scala.reflect.ClassTag
// animal input
trait AnimalInput {}
case class DogInput() extends AnimalInput
case class CatInput() extends AnimalInput
// animals
trait Animal[T <: AnimalInput] {
def getInput(implicit ct: ClassTag[T]): Class[T] = {
ct.runtimeClass.asInstanceOf[Class[T]]
}
}
object Dog extends Animal[DogInput] {}
object Cat extends Animal[CatInput] {}
我可以测试这个很好用:
println(Dog.getInput) // Success: "DogInput"
println(Cat.getInput) // Success: "CatInput"
问题是,当我在任何集合中引用这些对象时,我就遇到了麻烦:
// Failure: "No ClassTag available for animal.T"
List(Dog, Cat).foreach(animal => println(animal.getInput))
我想我理解为什么会发生这种情况,但我不确定如何解决这个问题。
提前感谢您的帮助!
1条答案
按热度按时间vqlkdk9b1#
实际上,我不能复制
No ClassTag available for animal.T
。您的代码在Scala 2.13.9:https://scastie.scala-lang.org/DmytroMitin/lonnNg0fR1qb4Lg7ChDBqg中编译和运行也许失败的意思是,对于集合,您不会收到类
DogInput
、CatInput
。T <: AnimalInput
复制了No ClassTag available for animal.T
,而不是类型参数:https://scastie.scala-lang.org/v79Y37eDRXuoauWA9b8uhQ*这个问题非常接近最近的问题Trying to extract the TypeTag of a Sequence of classes that extend a trait with different generic type parameters
请看那里的原因。
或者使用异类集合
或使用运行时反射
最简单的是
另一个选项是磁铁图案(12345 6)
您还可以将
ClassTag
隐式从方法移动到特征(并使特征成为抽象类)