使用默认构造函数

时间:2015-06-17 15:50:45

标签: scala reflection

我想用以下类实例化一个新对象:

class Test[T : ClassTag](val value : T) extends Serializable

private object Test {
  private var testClass : Class[_] = _

  def setTestClass(test : Class[_]) : Unit = {
    testClass = test
  }

  def apply[T : ClassTag](value : T) : Test[T] = {
    testClass.getConstructors()(0).newInstance(value).asInstanceOf[Test[T]]
  }
}

class Subtest[T : ClassTag](
    override val value : T, 
    val additional : Integer
) extends Test[T](value)

我在某处设置了setTestClass的测试类,该字符串已从字符串加载Class.forName。我们说它是"Subtest"。我想实例化一个新的Subtest[String] - 例如以下代码:

Test("my random string") // It should return a new Subtest[String]

问题是newInstance抛出java.lang.IllegalArgumentException: wrong number of arguments。我已经检查了parameterTypes的{​​{1}},并且有两种参数类型:

  • class java.lang.Object
  • interface scala.reflect.ClassTag

好。如何提供ClassTag?这里有什么问题? 有没有更好的方法,解决方法呢?

1 个答案:

答案 0 :(得分:3)

T: ClassTag语法称为上下文绑定。它是类型为ClassTag[T]的隐式参数的语法糖。换句话说,以下类签名是等效的:

class Test[T : ClassTag](val value : T)
class Test[T](val value: T)(implicit val ev: ClassTag[T])

所以你要找的构造函数需要另一个参数。使用上下文绑定语法时,您始终可以使用implicitly来获取所需的参数(由于上下文绑定的语义,因此保证存在该参数)。或者,当您知道classTag运算符可用时,可以使用ClassTag[T]运算符直接获取AnyRef的实例。

另一个细节是,在像这样的对象中使用类型参数时,它需要是apply

因此,您的def apply[T <: AnyRef : ClassTag](value : T) : Test[T] = { testClass.getConstructors.head.newInstance(value, classTag[T]).asInstanceOf[Test[T]] } 方法可能如下所示:

app.directive("dir", function(){
    return {
        restrict:"AE",
        scope: {},
        controller: function(){},
        templateUrl: "templates/testpostlink.html",
        compile: function(){
            return {
                pre: function(){
                },
                post:function(scope, EL, attrs){
                     // Here I am wondering how to get that div (let say scope.show is true)
                }
            };
        }// end of compile
    };
});