简体   繁体   English

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

[英]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方法为您提供TClass对象的权限。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM