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(Props [ new classobject * * ])

これは非常に醜いようです-これを行うためのより良い、よりエレガントな方法はありますか?

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
}

2番目のサンプルにはさらにいくつかの問題があります。

まずHashMap([String, String, ActorRef]("commonname" -> "Fqcn", someThing))、それはほぼ正しいですが、いくつかの重要な構文上の誤りがあります。

Scalaでは、[]型パラメーターを宣言または定義するために使用されますが、手元にあるのは定義の問題のようです。つまり、どの型パラメーターを記述したいのです。Scalaが型パラメーターを配置できる場所はごくわずかです。クラスのインスタンス化後(例new HashMap[String, Int])およびメソッド呼び出し(例)で適切なクラスlist.map[String](...)です。

したがって、typeパラメーターをのように配置するHashMap[String, String, ActorRef](...)ことは有効なScala構文であり、HashMapはコンパニオンオブジェクトであるため、のようなものを脱糖した後に終了しますHashMap.apply[String, String, ActorRef](...)

しかし、この式にはまだ大きな問題があります。HashMapは2つの型パラメーターのみを取ります。1つはキー用で、もう1つは値用です。コードを見ると、目的のキーはタプルであるように見えます。それでそれを機能させるために:HashMap[(String, String), ActorRef](...)

最後の修正ですがProps[new classobject]、タイプパラメータに関する混乱があります。タイプパラメータはインスタンスではなくタイプを取ります。「新しい何か」は何かのインスタンスを作成します。あなたはしなければなりませんProps[SomeClass]。簡単に言うと、「クラスオブジェクト」という用語は通常、クラス自体ではなく、クラスのインスタンスを指します。

2番目のサンプルの構文的に有効なバージョン:

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があり、代わりにインスタンス化を取得するアクタークラスの構成を取得し、そのシグネチャを確認します。

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] )) 
}

2番目のサンプルが最初のサンプルのクラスに何らかの形で依存すると仮定します。

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

これらのサンプルに関するいくつかのコメント:

  • 両方のタイプパラメータは不要です。コンパイラはそれからあなたのために推測することができます。
  • (a -> b, c)最初の要素がタプルであるタプルを定義するためにを使用する代わりに、を使用できます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拡張機能を作成し、渡されるExtendedActorSystemを取得し、「dynamicAccess」メソッドを介してそのDynamicAccessを取得し、それを使用してクラスをロードします。これは、Akka内のすべての動的クラスローディングに使用されるのと同じClassLoaderを使用します。これは、ActorSystemに渡すのと同じClassLoaderです。

于 2012-10-31T14:45:49.647 に答える