[英]Anonymous subclass of a parametric type by the use of ClassTag context bound
Given a concrete class of a given trait 给定具有特定特征的具体类别
trait Trt {
val x: Int
}
class C extends Trt {
val x: Int = 3
}
I'd like to create an object of an anonymous class of a parametric type in order to override the attribute x
我想创建一个参数类型的匿名类的对象,以覆盖属性
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)
}
}
The problem is that the compiler keeps reporting the following error: 问题在于,编译器不断报告以下错误:
>> Error:(26, 35) class type required but T found
Is instancing anonymous classes extenging parametric types classes even possible? 实例化匿名类甚至扩展参数类型类是否可能?
I know the problem is that T
is a type and not a class and I wonder if maybe, thanks to ClassTag bounded contex, it could be possible to instantiate withOverridenX
. 我知道这个问题是
T
是一种类型,而不是一类,我不知道,也许,这要归功于ClassTag界CONTEX,它可能是可能的实例withOverridenX
。
You can't instantiate T
since it is not known at runtime, just at compile time. 您不能实例化
T
因为它在运行时(在编译时)是未知的。 The ClassTag
would just give you acces to the Class
object of T
through the runtimeClass
method. ClassTag
只会通过runtimeClass
方法为您提供T
的Class
对象的权限。 But with just that, you can't subclass T
by calling new
, since there's for example no evidence that T
has a parameterless constructor. 但是仅此而已,您就无法通过调用
new
来继承T
,因为例如,没有证据表明T
具有无参数构造函数。
I found a workaround which allows to do exactly as I want which is: Get an instance of C
(or a subclass of C
) with a different value for x
than the one given at its declaration time. 我发现了一个解决方法,它允许做的正是我想要的是:获取的实例
C
(或子类C
与不同的值) x
比在其声明时给出的一个。
Whenever someone wants to abuse a programming language it is usual to turn to reflection. 每当有人想滥用一种编程语言时,通常都会转向反思。 Since version 2.10, Scala offers its own reflection capabilities (aside Java's) so it is possible to change
x
for withOverridenX
: 从版本2.10开始,Scala提供了自己的反射功能(除了Java之外),因此可以为
withOverridenX
更改x
:
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)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.