通过使用ClassTag上下文绑定的参数类型的匿名子类

时间:2015-05-08 09:22:56

标签: scala

给定特定特征的具体类

trait Trt {
    val x: Int
}

class C extends Trt {
    val x: Int = 3
}

我想创建一个参数类型的匿名类的对象,以覆盖属性x

abstract class SomeClass[T <: Trt : ClassTag] {
   def f: Unit = {
      val original = new C

      //Is this even possible?
      val withOverridenX = new T { override val x = 42}

      assert(original.x != withOverridenX.x)
   }
}

问题是编译器不断报告以下错误:

>> Error:(26, 35) class type required but T found

实现匿名类的实例化甚至可以扩展参数类型类吗?

我知道问题是T是一个类型而不是类,我想知道是否可能,由于ClassTag有界上下文,可以实例化withOverridenX

2 个答案:

答案 0 :(得分:1)

您无法实例化T,因为它在运行时不知道,只是在编译时。 ClassTag只会让您通过Class方法访问T runtimeClass对象。但就这一点而言,您不能通过调用T来对new进行子类化,因为例如没有证据表明T具有无参数构造函数。

答案 1 :(得分:0)

我找到了一个允许完全按照我的意愿执行的解决方法:获取C的实例(或C的子类),其x的值不同于x在宣布时间给出的一个。

每当有人想滥用编程语言时,通常会转向反思。从版本2.10开始,Scala提供its own reflection功能(除了Java),因此可以更改withOverridenX的{​​{1}}:

import scala.reflect.runtime.universe._

abstract class SomeClass[T <: Trt : TypeTag ] {
   def f: Unit = {
      val original = new C
      val withOverridenX = new C

      //This gets the term representation for the attribute 'x'...
      val xTerm = typeOf[T].declaration(newTermName("x")).asTerm

      //... which can be used to reflect the attribute:
      val m = runtimeMirror(getClass.getClassLoader)
      val reflectedC = m.reflect(withOverridenX)
      val reflectedX = reflectedC.reflectField(xTerm)

      reflectedX.set(42)

      assert(original.x != withOverridenX.x)
   }
}