2012-04-22 4 views
2
trait A extends Actor { 
    private val s = Set[Int]() 

    override def act() { 
    loop { 
     react { 
     // case code that modifies s 
     } 
    } 
    } 
} 

trait B extends Actor { 
    private val t = Set[String]() 

    override def act() { 
    loop { 
     react { 
     // case code that modifies t 
     } 
    } 
    } 
} 

val c = new C with A with B //...? 

私が本当にしたい、何が自動組み合わせるB.act() and C.act()ののいくつかの並べ替えですが、形質ミックスインで、唯一B.act()が呼び出されます。これを達成する簡単な方法はありますか?複数の形質ミックスインの問題と俳優

編集:ここにはhalf-solutionが見つかりました。元の特性がもはやActorに拡張されず、C with A with Bが動的ミキシンインではなくクラスとして定義される必要があるため、私は「半分」と言う。多分私はそれを「四半期解決策」と呼ぶべきでしょうか?

+0

はメッセージが 'A'と 'B'の両方によって受信されることができますか? – paradigmatic

+0

もちろん、どうしてですか?私が考案した解決法は、これを処理します。もし 'A'と' B'の両方がメッセージのためのcaseハンドラを持っていれば、後で混合される特性が解決に優先します。 (実際には、reduceをreduceLeftに変更する必要がありました。) –

+0

実際、私はあなたの質問を誤解している可能性があります。 'A'と' B' **は両方ともメッセージのケースハンドラを定義できますが、実際にはそれらのうちの1つだけが実行されます。しかし、あなたは**あなたが解決したいものを制御できます**。 –

答えて

1

あなたがABを変更する必要がないようにたぶん、あなたは、他の俳優のリストににメッセージを転送する形質を作ることができます:

trait C extends Actor { 
    private val acts: Seq[Actor] = Seq(new A{}, new B{}) 

    override def act() { 
    acts foreach (_.start) 
    loop { 
     react { case x => acts foreach { _ ! x } } 
    } 
    } 
} 

あなたはもちろん、抽象actsかを残すことができますこれをインスタンス化するときに別のセットでオーバーライドします。

import actors.Actor 

class MixableActor extends Actor { 
    protected var acts = List[PartialFunction[Any, Unit]]() 

    final override def act() { 
    loop { 
     react { 
     acts.reduce((a, b) => a orElse b) 
     } 
    } 
    } 

    final def receive(act: PartialFunction[Any, Unit]) { 
    acts = act :: acts 
    } 
} 

サンプルコード:

abstract class Node extends MixableActor { 
    ... 
} 

trait User extends MixableActor { 
    val files = scala.collection.mutable.Set[Data]() 
} 

trait Provider extends User { 
    receive({ 
    case ("provide", file: Data) => 
     provide(file) 
    }: PartialFunction[Any, Unit]) 
} 

trait Consumer extends User { 
    receive({ 
    case ("consume", file: Data) => 
     consume(file) 
    }: PartialFunction[Any, Unit]) 
} 

使用例:Actorクラスを拡張

+0

これは不可能で、 'A'と' B'は両方とも形質であり、インスタンス化できません。私はあなたが 'Seq(新しいC with A、新しいC with B)'を意味していると仮定していますが、これはメモリオーバーヘッドの可能性がある 'C'の* 2つのコピーにつながることに注意してください。それを無視して、これは大丈夫です。私たちは 'trait A extend D'と' trait B extend D'を持っています。今度は 'D'のパラメータを2つずつコピーしました! 'A'と' B'の両方に 'D'のパラメータを変更する場合がありますが、どのように同期させるのでしょうか? –

+1

@jiaweihli確かに可能です:上記のコードを見てください! 'new A {}'は 'Aを持つ新しいAnyref 'と同じです。私はDについてあなたの主張に従わない。俳優は可変状態を共有すべきではありません –

+0

ああ、私は括弧構文を知らなかった。 'A'のメッセージハンドラと' B'のメッセージハンドラの間のメッセージハンドラは一度に1つしか解決されないので、 'A'と' B'は可変状態を共有しません。すべての 'D'変数のコピーは1つだけでなければなりません。 あなたが提示したコードの問題は、メッセージハンドラがその特性の各インスタンスで解決するということです。したがって、 'D'の複数のコピーです。 –

1

val provider = new Node with Provider 
val consumer = new Node with Consumer 
val provider_and_consumer = new Node with Provider with Consumer 
関連する問題