Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 将类作为值传递并创建实例_Scala - Fatal编程技术网

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

Scala 将类作为值传递并创建实例,scala,Scala,我有许多共同的基本特征。我有一个函数,需要为这些类中的一个类的实例创建一个新实例,但只有在运行时才知道哪个类 是否可以将该类作为参数传递,并在Scala中的运行时创建实例 我甚至不确定答案是否是最好的方法,但目前这是我唯一能想到的 您可以这样传递值: myFunc(classOf[myObj]) 对签名方法的改进 def myFunc(clazz : AnyRef)={ ... 但这闻起来很难闻。您正在考虑实现一个,或者更好的是,您可以使用多态性,只需执行以下操作: myObj.myFunc

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

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


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

您可以这样传递值:

myFunc(classOf[myObj])
对签名方法的改进

def myFunc(clazz : AnyRef)={ ...
但这闻起来很难闻。您正在考虑实现一个,或者更好的是,您可以使用多态性,只需执行以下操作:

myObj.myFunc
因为您的功能取决于所涉及的类。

与Java中的相同:

classOf[MyClass].newInstance // calls the constructor without parameters
classOf[MyClass].getConstructor(/* parameter types */).newInstance(/* parameters */)


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

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

但是,您可以为该类创建生成器,如下所示:

trait Builder[A]{
   def newItem:A
}
然后将适当的生成器传递给func

def myFunc[A](param1:B,builder:Builder[A])
你也可以利用它

def myFunc[A](param1:B)(implicit builder:Builder[A])

也许您可以详细介绍一下您的用例?

我个人会避免反思

如果您可以预先确定所有可能的用例,并使用标识符对它们进行分类:

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的建议

获得您想要的最“无缝”的方法是将执行实例化的方法声明为具有上下文绑定为
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]
  }
}
这仅在有问题的类没有arg构造函数时才起作用。您可以使用参数调用构造函数,但这要复杂得多。您必须熟悉Java反射API

在答复中:

scala> import rrs.scribble.Maker._
import rrs.scribble.Maker._

scala> class Argless
defined class Argless

scala> val s1 = maker[Argless]
s1: Argless = Argless@1512d075

我想我会使用工厂模式(没有人喜欢有臭味的代码)。我知道这一点,但它们仍然可用,并且有一个替代品,因此这种策略可以工作,并且如图所示,可以在2.8到2.10版本之间移植(至少)。