【问题标题】:In Scala, is it possible to instantiate an object of generic type T? [duplicate]在 Scala 中,是否可以实例化泛型类型 T 的对象? [复制]
【发布时间】:2020-11-27 15:24:40
【问题描述】:

在 Scala 中,即使解决方案不优雅,是否可以实例化/创建泛型类型 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))

【问题讨论】:

标签: scala generics reflection types scala-reflect


【解决方案1】:

从技术上讲,可以使用反射。例如,您可以使用 ClassTag 捕获类型 T 的运行时类,然后找到适当的构造函数并创建实例:

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

它应该可以工作,但最好避免这种方法,因为你会失去所有类型安全性。

【讨论】:

  • 感谢@Krzysztof。这就是我要找的。它看起来不错,但似乎抛出错误:“类型不匹配”找到:Seq[Any],需要:Seq[Object]
  • 哦,我明白了,这是因为输入是 Any 类型,而构造函数来自 Java,期望类型为 Object。
【解决方案2】:

不,这是不可能的。 T 是一个参数。你对它一无所知任何。你甚至不知道它是否可以被实例化根本。它可能是 trait 或抽象类或单例类型或复合类型。

这就是参数多态的重点。编写不需要知道它所处理的类型的任何代码。

举个例子,这样调用你的方法是完全合法的:

val goodLuck = createObject[Nothing](Seq(1, 2))

嗯,Nothing 字面意思定义为“不能有实例的类型”。你将如何实例化它?

【讨论】:

  • 我明白了,谢谢 Jorg。只是好奇,如果 T 从我知道有构造函数的类扩展,在语法上是否可以实例化泛型类型 T?
  • 您可以使用隐式证据来提供一些工厂 - 如果类型具有隐式,您可以使用它来创建实例。但是传递Any 的序列确实是一个糟糕的设计,您最多可以返回Option[T] 以表明参数可能与预期的类不匹配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-26
  • 2022-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多