在运行时使用默认构造函数实例化类型参数化 class
Instantiate type-parametrized class at runtime with default constructor
我想用以下 classes 实例化一个新对象:
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)
我在某处设置了 test-class 和 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
。我检查了Constructor
的parameterTypes
,有两种参数类型:
- class java.lang.Object
- 界面scala.reflect.ClassTag
好的。如何提供 ClassTag?这里有什么问题?
有没有更好的方法和解决方法?
T: ClassTag
语法称为 上下文绑定 。它是 ClassTag[T]
类型隐式参数的语法糖。换句话说,以下 class 个签名是等价的:
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]]
}
我想用以下 classes 实例化一个新对象:
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)
我在某处设置了 test-class 和 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
。我检查了Constructor
的parameterTypes
,有两种参数类型:
- class java.lang.Object
- 界面scala.reflect.ClassTag
好的。如何提供 ClassTag?这里有什么问题? 有没有更好的方法和解决方法?
T: ClassTag
语法称为 上下文绑定 。它是 ClassTag[T]
类型隐式参数的语法糖。换句话说,以下 class 个签名是等价的:
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]]
}