我有许多共同基本特征的类。我有一个函数需要创建这些类之一的实例的新实例,但哪一个只在运行时知道。
是否可以将此类作为参数传递并在Scala中在运行时创建实例?
我甚至不确定答案是最好的方法,但目前这是我唯一能想到的。
答案 0 :(得分:4)
你可以传递这个值:
myFunc(classOf[myObj])
带签名的方法
def myFunc(clazz : AnyRef)={ ...
但这闻起来很糟糕。你是在考虑实现一个factory pattern,还是更好的是你可以使用多态而只是这样做:
myObj.myFunc
因为您的功能取决于所涉及的类。
答案 1 :(得分:2)
与Java相同:
classOf[MyClass].newInstance // calls the constructor without parameters
classOf[MyClass].getConstructor(/* parameter types */).newInstance(/* parameters */)
这适用于任何Scala版本。 Scala 2.10有new reflection libraries,它们都知道Scala的概念。
答案 2 :(得分:1)
我建议尽量避免反思,因为它很容易导致难以测试的代码和运行时异常。
但是,您可以为该类创建一个构建器,如下所示:
trait Builder[A]{
def newItem:A
}
然后将适当的构建器
传递给您的funcdef myFunc[A](param1:B,builder:Builder[A])
你也可以利用暗示
def myFunc[A](param1:B)(implicit builder:Builder[A])
也许你可以详细说明一下你的用例?
答案 3 :(得分:0)
我个人会避免反思。
如果您能事先识别所有可能的用例并使用标识符对其进行分类:
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的建议
答案 4 :(得分:0)
获得所需内容的最“无缝”方式是将实例化的方法声明为具有上下文绑定为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