在Scala中,如何在所有子类中引用已实现的抽象类型的ClassTag?

时间:2016-05-19 08:57:01

标签: scala type-erasure abstract-type

如果我有1个特征和2个对象:

trait MyClass {
  type T <: MyClass

  def foo(): ClassTag[T] = {...}
}

object ChildClass1 extends MyClass {
   type T = String
}

object ChildClass2 extends MyClass {
   type T = Option[String]
}

是否可以在MyClass中实现foo(),以便ChildClass1.foo()产生ClassTag [String],而ChildClass2.foo()产生ClassTag [Option]。

如果没有,绕过它最简单的方法是什么?应该注意的是,T的实现可能是内部类/对象,因此黑客反射可能会产生一些副作用。

2 个答案:

答案 0 :(得分:0)

我想提出一个肮脏和有缺陷的答案,如果你有任何更好的想法,请告诉我:

  lazy val mf: ClassTag[T] = {

    val clazz = this.getClass
    val name = clazz.getName
    val modifiedName = name + "T"
    val reprClazz = Utils.classForName(modifiedName)

    Manifest.classType(reprClazz)
  }

仅当子类是单个对象时才有效。

答案 1 :(得分:0)

好吧,我可能没有完全理解你的目标,但从我所看到的,你正在尝试创建一个具有上限类型的特征,你也希望能够要在运行时获取类型,请更正?

因此,我们假设您有一个Foo特征:

class MyClass // not important

trait Foo[T <: MyClass] {
  def foo: ClassTag[T]
}

如果你想要一个对象实现,解决方案是微不足道的,因为你知道编译时的类型:

class MyClassSubclass extends MyClass // also not important

object FooObject extends Foo[MyClassSubclass] {
  def foo: ClassTag[MyClassSubclass] = ClassTag(classOf[MyClassSubclass])
}

但是如果你想要一个类,那么你可以用一个非常易读的方式解决implicitly +上下文绑定组合的问题:

class FooImpl[T <: MyClass : ClassTag] extends Foo[T] {
  def foo: ClassTag[T] = implicitly[ClassTag[T]]
}