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
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
.
You can't instantiate T
since it is not known at runtime, just at compile time. The ClassTag
would just give you acces to the Class
object of T
through the runtimeClass
method. 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.
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.
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
:
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)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.