2

任何人都知道如何在 Scala (2.10) 中动态分配一个类?我有一些课程 MyClass。我正在使用 Akka (2.0),我真的很想能够做类似的事情:

classnames = List[String]("fqcn", "fqcn", fqcn"....]
for (name <- classnames) {
     val clazz = classLoader.load(name)
     val actRef = actorSystem.actorOf(Props[clazz])
}

但是,Akka 还有其他限制。所以我能做的最好的(我认为)是:

val activeClasses = HashMap([String, String, ActorRef]
     ("commonname" -> 
       "Fqcn", actorOf(Props[new classobject]])
  )

其中 classobject 是文字类,而不是类加载器的名称引用。我真的必须在某处编译该类并执行

actorOf(道具[类对象* * ])

这看起来很丑陋——有没有更好、更优雅的方法来做到这一点?

4

3 回答 3

3

修复您提供的第一个示例,请参阅评论:

classnames = List[String]("fqcn", "fqcn", "fqcn"....) // close ( with ) not ]
for (name <- classnames) {
     val clazz = classLoader.forName(name) // forName is what loads a class
     //val actRef = actorSystem.actorOf(Props[clazz]) // still wrong I will explain later
}

第二个示例还有一些问题。

首先HashMap([String, String, ActorRef]("commonname" -> "Fqcn", someThing)),它几乎是正确的,但有一些关键的句法错误。

在 Scala[]中用于声明或定义类型参数,看来我们手头的案例是定义问题,换句话说,我们要声明什么类型参数。只有少数地方 Scala 允许放置类型参数,在类实例化之后(例如new HashMap[String, Int])和方法调用中(例如list.map[String](...).

因此,将类型参数放置为 inHashMap[String, String, ActorRef](...)将是有效的 Scala 语法,并且由于 HashMap 是伴生对象,因此在对HashMap.apply[String, String, ActorRef](...).

但是这个表达式还有一个很大的问题,HashMap 只带了两个类型参数,一个是键,一个是值。查看您的代码,似乎所需的键是一个元组。所以要让它工作:HashMap[(String, String), ActorRef](...)

现在进行最后一次修复Props[new classobject],再次混淆类型参数。类型参数采用类型而不是实例,任何“新事物”都将创建某事物的实例。你必须做Props[SomeClass]。作为快速方面,术语“类对象”通常指的是类的实例,而不是类本身。

第二个样本的语法有效版本:

val activeClasses = HashMap[(String, String), ActorRef](
   ("commonname" ->  "Fqcn", actorOf(Props[SomeClass]))
)

回到第一个示例和这一行:

val actRef = actorSystem.actorOf(Props[clazz])

clazz这是 Class[_] 的一个实例,上面的代码甚至都不是有效代码。这似乎Props.apply[T <: ActorRef]...需要一个类型,它会为您处理实例化它。但是您只有包含类的 Class[_]。如何解决这个问题?碰巧有另一个 Props.apply 代替了将要进行实例化的actor类的构造,看看它的签名:

def apply(creator: ⇒ Actor)

为什么不使用这个?

classnames = List[String]("fqcn", "fqcn", "fqcn"....)
for (name <- classnames) {
     val clazz = classLoader.forName(name)
     val actRef = 
        actorSystem.actorOf(Props( clazz.newInstance.asInstanceOf[Actor] )) 
}

假设第二个样本会以某种方式依赖第一个样本:

val activeClasses = HashMap[(String, String), ActorRef](
   ("commonname" ->  "Fqcn", 
     actorOf(Props( clazz.newInstance.asInstanceOf[Actor] ) )
)

关于这些样本的一些评论:

  • 这两个类型参数都是不必要的。编译器可以为您推断。
  • 除了使用(a -> b, c)for 定义其第一个元素是元组的元组,您可以使用a -> b ->,这将导致((a,b),c). ->是左关联的。
于 2012-10-31T03:59:29.153 回答
2

由于 clazz 来自 classLoader,因此无法使用 Props[] 来创建 ActorRef

所以Props.apply改用

actorOf(Props(clazz.newInstance.asInstanceOf[Actor]))
于 2012-10-31T02:30:29.867 回答
2

这在 Akka 邮件列表中得到了回答:https ://groups.google.com/group/akka-user/browse_thread/thread/6823203b3c8470be/8ad21fcfb39b0e25?lnk=gst&q=dynamicAccess

简而言之,创建一个处理动态类加载的Akka Extension并获取传入的ExtendedActorSystem,通过“dynamicAccess”方法获取其DynamicAccess并使用该方法加载类。这将使用与 Akka 中所有动态类加载相同的 ClassLoader,它与您传递给 ActorSystem 的 ClassLoader 相同。

于 2012-10-31T14:45:49.647 回答