将类作为值传递并创建实例

时间:2013-01-14 10:44:00

标签: scala

我有许多共同基本特征的类。我有一个函数需要创建这些类之一的实例的新实例,但哪一个只在运行时知道。

是否可以将此类作为参数传递并在Scala中在运行时创建实例?

我甚至不确定答案是最好的方法,但目前这是我唯一能想到的。

5 个答案:

答案 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 */)

请参阅Javadoc for Class

这适用于任何Scala版本。 Scala 2.10有new reflection libraries,它们都知道Scala的概念。

答案 2 :(得分:1)

我建议尽量避免反思,因为它很容易导致难以测试的代码和运行时异常。

但是,您可以为该类创建一个构建器,如下所示:

trait Builder[A]{
   def newItem:A
}

然后将适当的构建器

传递给您的func
def 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