我有许多类的共同基本特征。我有一个函数需要创建这些类之一的实例的新实例,但只有在运行时才知道哪一个。
是否可以将此类作为参数传递并在运行时在 Scala 中创建实例?
我什至不确定答案是否是最好的方法,但目前这是我唯一能想到的。
我有许多类的共同基本特征。我有一个函数需要创建这些类之一的实例的新实例,但只有在运行时才知道哪一个。
是否可以将此类作为参数传递并在运行时在 Scala 中创建实例?
我什至不确定答案是否是最好的方法,但目前这是我唯一能想到的。
您可以这样传递值:
myFunc(classOf[myObj])
到带有签名的方法
def myFunc(clazz : AnyRef)={ ...
但这闻起来很糟糕。您正在考虑实现工厂模式,或者更好的是您可以使用多态性并简单地执行以下操作:
myObj.myFunc
因为您的功能取决于所涉及的类。
我建议尽量避免反射,因为它很容易导致难以测试的代码和运行时异常。
但是,您可以为该类创建一个构建器,如下所示:
trait Builder[A]{
def newItem:A
}
然后将适当的构建器传递给您的函数
def myFunc[A](param1:B,builder:Builder[A])
你也可以利用隐式
def myFunc[A](param1:B)(implicit builder:Builder[A])
也许您可以详细说明您的用例?
获得所需内容的最“无缝”方式是将执行实例化的方法声明为具有上下文绑定的类型参数ClassManifest
def maker[T : ClassManifest](args...): T = ...
这将导致编译器自动将一个实例传递ClassManifest[T]
给 maker。调用者只需要指定他们想要实例化的特定类。
package rrs.scribble
import scala.reflect.ClassManifest
object Maker
{
def maker[T : ClassManifest]: T = {
val cmT = implicitly[ClassManifest[T]]
val cT = cmT.runtimeClass
cT.newInstance.asInstanceOf[T]
}
}
这只适用于有问题的类的无参数构造函数。您可以使用参数调用构造函数,但涉及更多。您必须熟悉 Java 反射 API。
在 REPL 中:
scala> import rrs.scribble.Maker._
import rrs.scribble.Maker._
scala> class Argless
defined class Argless
scala> val s1 = maker[Argless]
s1: Argless = Argless@1512d075
我个人会避免反思。
如果您可以事先识别所有可能的用例并使用标识符对其进行分类:
trait SUPER
class A extends SUPER
class B extends SUPER
class C extends SUPER
class D extends SUPER
val idA = 'CLASS_A
val idB = 'CLASS_B
val idC = 'CLASS_C
val idD = 'CLASS_D
def build(selectedId: Symbol): SUPER = selectedId match {
case 'CLASS_A => new A
case 'CLASS_B => new B
case 'CLASS_C => new C
case 'CLASS_D => new D
}
否则,如果您更喜欢建筑商,我会遵循 @Edmondo1984 的建议