在 Scala 中,是否可以实例化泛型类型 T 的对象?
In Scala, is it possible to instantiate an object of generic type T?
在Scala中,即使解决方案不优雅,是否可以instantiate/create一个泛型类型T的新对象?是否可以使用反射来实现?
例如,我对以下内容感兴趣:
case class Person(name: String, age: Int)
假设我想执行以下操作来创建一个 Person 类型的对象:
def createObject[T](fieldValues: Seq[Any]): T = {
... T(fieldValues)
}
val person = createObject[Person](Seq("Bob", 20))
不,这是不可能的。 T
是一个参数。你对它一无所知。您甚至根本不知道它是否可以实例化。它可能是特征或抽象 class 或单例类型或复合类型。
也就是参数多态的整点。编写不需要了解所处理的类型的任何代码。
举个例子,这样调用你的方法是完全合法的:
val goodLuck = createObject[Nothing](Seq(1, 2))
嗯,Nothing
字面上 定义为“不能有实例的类型”。你打算如何实例化它?
从技术上讲,可以使用反射。例如,您可以使用 ClassTag
捕获类型 T 的运行时 class,然后找到合适的构造函数并创建实例:
def createObject[T](fieldValues: Seq[Any])(implicit ct: ClassTag[T]): Option[T] = {
//we lookup for matching constructor using arguments count, you might also consider checking types
ct.runtimeClass.getConstructors.find(_.getParameterCount == fieldValues.size)
.flatMap {constructor =>
Try(constructor.newInstance(fieldValues: _*).asInstanceOf[T]).toOption
}
}
createObject[Person](Seq("Bob", 20)) //Some(Person("Bob", 20))
createObject[Person](Seq(20, 10)) //None
如果没有构造函数匹配参数,该函数将失败返回 None
。
它应该可行,但最好避免使用这种方法,因为这样会失去所有类型安全性。
在Scala中,即使解决方案不优雅,是否可以instantiate/create一个泛型类型T的新对象?是否可以使用反射来实现?
例如,我对以下内容感兴趣:
case class Person(name: String, age: Int)
假设我想执行以下操作来创建一个 Person 类型的对象:
def createObject[T](fieldValues: Seq[Any]): T = {
... T(fieldValues)
}
val person = createObject[Person](Seq("Bob", 20))
不,这是不可能的。 T
是一个参数。你对它一无所知。您甚至根本不知道它是否可以实例化。它可能是特征或抽象 class 或单例类型或复合类型。
也就是参数多态的整点。编写不需要了解所处理的类型的任何代码。
举个例子,这样调用你的方法是完全合法的:
val goodLuck = createObject[Nothing](Seq(1, 2))
嗯,Nothing
字面上 定义为“不能有实例的类型”。你打算如何实例化它?
从技术上讲,可以使用反射。例如,您可以使用 ClassTag
捕获类型 T 的运行时 class,然后找到合适的构造函数并创建实例:
def createObject[T](fieldValues: Seq[Any])(implicit ct: ClassTag[T]): Option[T] = {
//we lookup for matching constructor using arguments count, you might also consider checking types
ct.runtimeClass.getConstructors.find(_.getParameterCount == fieldValues.size)
.flatMap {constructor =>
Try(constructor.newInstance(fieldValues: _*).asInstanceOf[T]).toOption
}
}
createObject[Person](Seq("Bob", 20)) //Some(Person("Bob", 20))
createObject[Person](Seq(20, 10)) //None
如果没有构造函数匹配参数,该函数将失败返回 None
。
它应该可行,但最好避免使用这种方法,因为这样会失去所有类型安全性。