Reputation: 5376
I want to instantiate a new object with the following 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)
I set the test-class with setTestClass
somewhere, that has been loaded with Class.forName
from a string. Let say it is "Subtest"
. I wish to instantiate a new Subtest[String]
with - for example the following code:
Test("my random string") // It should return a new Subtest[String]
The problem is that newInstance
throws java.lang.IllegalArgumentException: wrong number of arguments
. I've checked the parameterTypes
of the Constructor
, and there are two parameter types:
Okay. How to supply the ClassTag? What is the problem here? Is there a better approach, workaround for this?
Upvotes: 1
Views: 1557
Reputation: 16324
The T: ClassTag
syntax is called a context bound. It is syntactic sugar for an implicit parameter of type ClassTag[T]
. In other words, the following class signatures are equivalent:
class Test[T : ClassTag](val value : T)
class Test[T](val value: T)(implicit val ev: ClassTag[T])
So the constructor you're looking for expects another parameter. When using the context-bound syntax, you can always use the implicitly
to get the desired parameter (which is guaranteed to exist because of the semantics of the context bound). Alternatively, you can use the classTag
operator to directly get an instance of ClassTag[T]
when you know it is available.
Another detail is that when using a type parameter in an object like this, it needs to be an AnyRef
.
So your apply
method might look like:
def apply[T <: AnyRef : ClassTag](value : T) : Test[T] = {
testClass.getConstructors.head.newInstance(value, classTag[T]).asInstanceOf[Test[T]]
}
Upvotes: 3