2013-08-27 5 views
10

Sto creando più tratti che estendono l'attore. Quindi voglio creare una classe attore che usi alcuni di questi tratti. Tuttavia, non sono sicuro di come combinare i metodi di ricezione da tutti i tratti nel metodo di ricezione della classe attore.impilamento di tratti multipli negli attori Akka

Tratti:

trait ServerLocatorTrait extends Actor { 
    def receive() = { 
     case "s" => println("I'm server ") 
    } 
    } 

    trait ServiceRegistrationTrait extends Actor { 
    def receive() = { 
     case "r" => println("I'm registration ") 
    } 
    } 

L'attore:

class FinalActor extends Actor with ServiceRegistrationTrait with ServerLocatorTrait { 
    override def receive = { 
    super.receive orElse ??? <--- what to put here 
    } 
} 

Ora, se io mando "r" e "s" per FinalActor va solo in ServerLocatorTrait - che è l'ultimo tratto aggiunto. Così il modo in cui funziona in questo momento è che si considera eccellente l'ultimo tratto aggiunto, quindi in questo caso ServerLocatorTrait

Domanda:
Come faccio a combinare la ricezione metodi da tutti i tratti in FinalActor?

PS - ho visto gli attori con react esempio: http://www.kotancode.com/2011/07/19/traits-multiple-inheritance-and-actors-in-scala/ ma non è quello che mi serve

+0

possibile duplicato di [Scala impilabile modello tratto con gli attori Akka] (http://stackoverflow.com/questions/18124643/scala-stackable-trait-pattern-with-akka-actors) – cmbaxter

+0

@cmbaxter Non vedo come potrebbe essere un duplicato di quello. Sebbene forse quell'OP potesse usare ciò che ho scelto come soluzione. – Adrian

risposta

17

non sono sicuro se è possibile combinare la ricezione metodi, in quanto ciò comporterebbe chiamare super-del super per ottenere il metodo receiveServiceRegistration. Sarebbe anche molto confuso.

Un altro modo sarebbe dare nomi diversi al metodo receive nei tratti.

trait ServerLocatorTrait extends Actor { 
    def handleLocation: Receive = { 
    case "s" => println("I'm server ") 
    } 
} 

trait ServiceRegistrationTrait extends Actor { 
    def handleRegistration: Receive = { 
    case "r" => println("I'm registration ") 
    } 
} 

class FinalActor extends Actor with ServiceRegistrationTrait with ServerLocatorTrait { 
    def receive = handleLocation orElse handleRegistration 
} 

object Main extends App { 

    val sys = ActorSystem() 

    val actor = sys.actorOf(Props(new FinalActor)) 

    actor ! "s" 
    actor ! "r" 

    sys.shutdown() 

} 

è ancora possibile si utilizza approccio iniziale, ma è necessario catena super.receive per ogni tratto misto.

trait IgnoreAll extends Actor { 
    def receive: Receive = Map() 
} 

trait ServerLocatorTrait extends Actor { 
    abstract override def receive = ({ 
    case "s" => println("I'm server ") 
    }: Receive) orElse super.receive 
} 

trait ServiceRegistrationTrait extends Actor { 
    abstract override def receive = ({ 
    case "r" => println("I'm registration ") 
    }: Receive) orElse super.receive 
} 

class FinalActor extends IgnoreAll with ServiceRegistrationTrait with ServerLocatorTrait 

Quest'ultima soluzione mi sembra abbastanza brutta.

prega di consultare il link qui sotto per una discussione più dettagliata sul tema:

Extending Actors using PartialFunction chaining

+0

Mi piace la tua prima soluzione e penso che la userò (mostra più di quello che sta succedendo); Inizialmente cercavo qualcosa come la tua seconda soluzione. – Adrian

+0

Le tue caratteristiche potrebbero essere dichiarate come: tratto ServerLocatorTrait {this: Actor => ....}, perché non sono attori reali da soli. Con questa sintassi dici "Questo tratto sarà mixato con un attore". –