我正面临着Scala反射和泛型的问题。我有一个抽象类,它有这个签名:
IPartition [T <: IPartition[T]] (val bounds: Array[BoundsInOneDimension],
val boxId: BoxId = 0, val partitionId: Int = -1, var adjacentPartitions: List[T] = Nil)
以及具有此签名的具体类:
Box (bounds: Array[BoundsInOneDimension], boxId: BoxId = 0, partitionId: Int = -1, adjacentBoxes: List[Box] = Nil)
extends IPartition[Box] (bounds, boxId, partitionId, adjacentBoxes)
我想做的是在object
的通用方法中实例化具体类。因此,我有这个方法:
myMethod[SHAPE <: IPartition[SHAPE]] (...) (implicit m:Manifest[SHAPE]): Iterable[SHAPE]
并且在这个方法中我需要实例化扩展上面抽象类的泛型类SHAPE。
到现在为止,我已经尝试过这样做了:
m.getClass.getConstructors.apply(0).newInstance(combinations(i).reverse , Int.box(i+1), Int.box(-1)).asInstanceOf[SHAPE]
但是我得到了java.lang.IllegalArgumentException
。然后我打印了构造函数所期望的参数:
class scala.Option
class java.lang.Class
class scala.collection.immutable.List
我无法理解这一点。我期待4个参数,或1,或类似的东西。此外,我没想到scala.Option
是第一个参数,java.lang.Class
也不是第二个参数。
我无法理解如何使用正确的参数正确实例化我需要的类。愿任何人帮助我吗?
*更新*
现在,我已尝试根据@ dk14响应
执行此操作for (i <- 0 until combinations.size) yield classTag.runtimeClass.getConstructors.apply(0).newInstance(combinations(i).reverse , Int.box(i+1), Int.box(-1), Nil:List[SHAPE]).asInstanceOf[SHAPE]
我得到java.lang.IllegalArgumentException: argument type mismatch
。我无法理解我所缺少的东西......
*更新2 *
在这种情况下,我的问题很愚蠢。问题是我传递了List
而不是Array
作为第一个参数。修正了这一切,一切都对我有用。
感谢。 马可
答案 0 :(得分:2)
至少它适用于ClassTag
(Manifest
s已被弃用 - 甚至没有尝试过):
import scala.reflect._
scala> def myMethod[SHAPE <: IPartition[SHAPE]: ClassTag] (bs: Object, bi: Object, p: Object, a: Object) = classTag[SHAPE].runtimeClass.getConstructors()(0).newInstance(bs, bi, p, a)
myMethod: [SHAPE <: IPartition[SHAPE]](bs: Object, bi: Object, p: Object, a: Object)(implicit evidence$1: scala.reflect.ClassTag[SHAPE])Any
scala> myMethod[Box](Array(1,2,3), 1: Integer, 1: Integer, List[Box]())
res27: Any = Box@3305055b
我假设BoundsInOneDimension
和BoxId
是整数,但不认为它会改变任何东西。 Scala 2.11.2在这里。
以下是getConstructors()(0).getParameterTypes()
:
Array(class [I, int, int, class scala.collection.immutable.List) //`class [I` means Array of integers
你也可以使用TypeTag
和Scala Reflection(而不是Java),这是更安全的类型 - How to get constructor arguments in a method using typetags/mirrors?。像那样:
def creator[T <: IPartition[T] : TypeTag]() = {
val m = ru.runtimeMirror(getClass.getClassLoader)
val classType = ru.typeOf[T].typeSymbol.asClass
val constructor = typeTag[T].tpe.declaration(ru.nme.CONSTRUCTOR).asMethod
val constructorMethod = m.reflectClass(classType).reflectConstructor(constructor)
constructorMethod.apply(Array.empty[Int],2,3,List.empty[Box])
}