任何人都知道如何在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(道具[新 classobject * * ])
这看起来非常难看 - 是否有更好,更优雅的方式来做到这一点?
答案 0 :(得分: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](...)
。
因此,将类型参数放在HashMap[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)
,而不是使用a -> b ->
来定义第一个元素是元组的元组,而((a,b),c)
将导致->
。 {{1}}是左关联的。答案 1 :(得分:2)
由于clazz来自classLoader,因此无法使用Props []创建ActorRef
所以请改用Props.apply
actorOf(Props(clazz.newInstance.asInstanceOf[Actor]))
答案 2 :(得分:2)
简而言之,创建一个处理动态类加载的Akka扩展并获取传入的ExtendedActorSystem,通过“dynamicAccess”方法获取其DynamicAccess并使用它加载类。这将使用与Akka中所有动态类加载相同的ClassLoader,它与传递给ActorSystem时的ClassLoader相同。