给定特定特征的具体类
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
。
答案 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)
}
}