¿Cómo usar un patrón de rasgo apilable con los actores AKKA? -- scala campo con akka campo con traits camp Relacionados El problema

How to use stackable trait pattern with Akka actors?


19
vote

problema

Español

Estoy tratando de implementar un PUB / SUB TRATIS para mezclar en otros actores AKKA utilizando un rasgo apilable.

Aquí está lo que vino:

  trait PubSubActor extends Actor {   abstract override def receive =      super.receive orElse {       case Subscribe(topic) => /* ... */       case Publish(topic, msg) => /* ... */     } }  class MyActor extends Actor with PubSubActor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */   } }   

En qué punto, el compilador lanza un error: Error: Método de anulación Recibir en Rasit Myactor ... Método Recibir necesidades 'Modificadores de anulación abstracta'.

¿Puedes explicarme por qué esto no funciona? ¿Cómo puedo arreglarlo para que funcione?

¡Gracias!

actualización

Las siguientes obras:

  trait PubSubActor extends Actor {   abstract override def receive =      super.receive orElse {       case Subscribe(topic) => /* ... */       case Publish(topic, msg) => /* ... */     } }  class MyActor extends Actor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */   } }  class MyActorImpl extends MyActor with PubSubActor   

¿Pero por qué? ¿Por qué puedo obtener el comportamiento que quiero de esta manera, pero no el otro? Cualquier motivo? Parece que no puedo averiguar la diferencia subyacente entre estas dos muestras que marcan la diferencia.

Original en ingles

I'm trying to implement a Pub/Sub trait to mix into other akka actors using a stackable trait.

Here is what I came up with:

trait PubSubActor extends Actor {   abstract override def receive =      super.receive orElse {       case Subscribe(topic) => /* ... */       case Publish(topic, msg) => /* ... */     } }  class MyActor extends Actor with PubSubActor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */   } } 

At which point, the compiler throws back an error: error: overriding method receive in trait MyActor... method receive needs `abstract override' modifiers.

Can you explain to me why this isn't working? How can I fix it so it works?

Thanks!

UPDATE

The following works:

trait PubSubActor extends Actor {   abstract override def receive =      super.receive orElse {       case Subscribe(topic) => /* ... */       case Publish(topic, msg) => /* ... */     } }  class MyActor extends Actor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */   } }  class MyActorImpl extends MyActor with PubSubActor 

But why? Why can I get the behavior I want this way but not the other? Any reasons? I can't seem to figure out the underlying difference between these two samples that makes the difference.

        
 
 

Lista de respuestas

17
 
vote

Hay una solución simple y concisa:

Defina un rasgo de recepción que cae varias funciones de recepción usando <div id="higher" class="high">Hey there</div>9 :

  /* theme CSS rule */  .parent .child {    color: red;    background: blue;  }      /* custom CSS rule - loaded/ordered after */  .parent .child {    color: yellow;    background: lightgray;  }0  

Usando esto en los actores es fácil:

  /* theme CSS rule */  .parent .child {    color: red;    background: blue;  }      /* custom CSS rule - loaded/ordered after */  .parent .child {    color: yellow;    background: lightgray;  }1  

Se llamarán la primera recepción de Pubsubactor. Si el mensaje no fue manejado, se pasará a la recepción de Myactor.

 

There's a simple and concise solution:

Define a Receiving trait that chains multiple receive functions using orElse :

trait Receiving {    var receivers: Receive = Actor.emptyBehavior    def receiver(next: Actor.Receive) { receivers = receivers orElse next }   def receive = receivers // Actor.receive definition } 

Using this in actors is easy:

trait PubSubActor extends Receiving {   receiver {     case Publish => /* I'm the first to handle messages */   } }  class MyActor extends PubSubActor with Receiving {   receiver {     case SomeMessage => /* PubSubActor didn't handle, I receive the message */    } } 

First PubSubActor's receive will be called. If message wasn't handled it will be passed to MyActor's receive.

 
 
         
         
9
 
vote

Ciertamente puede lograr lo que está buscando con la función de actor compuesto de Akka. Esto se describe un poco en Extender actores que se extienden a la encadenamiento de funciones parcialfunction .

Primero, el código de infraestructura (directamente desde los documentos):

  /* theme CSS rule */  .parent .child {    color: red;    background: blue;  }      /* custom CSS rule - loaded/ordered after */  .parent .child {    color: yellow;    background: lightgray;  }2  

Luego, los comportamientos que desea poder componer en los actores:

  /* theme CSS rule */  .parent .child {    color: red;    background: blue;  }      /* custom CSS rule - loaded/ordered after */  .parent .child {    color: yellow;    background: lightgray;  }3  

y, por último, un actor real que utiliza estos comportamientos componeables:

  /* theme CSS rule */  .parent .child {    color: red;    background: blue;  }      /* custom CSS rule - loaded/ordered after */  .parent .child {    color: yellow;    background: lightgray;  }4  
 

You can certainly achieve what you are looking for using Akka's composable actor feature. This is described a bit in Extending Actors using PartialFunction chaining.

First, the infrastructure code (straight from the docs):

class PartialFunctionBuilder[A, B] {   import scala.collection.immutable.Vector    // Abbreviate to make code fit   type PF = PartialFunction[A, B]    private var pfsOption: Option[Vector[PF]] = Some(Vector.empty)    private def mapPfs[C](f: Vector[PF] => (Option[Vector[PF]], C)): C = {     pfsOption.fold(throw new IllegalStateException("Already built"))(f) match {       case (newPfsOption, result) => {         pfsOption = newPfsOption         result       }     }   }    def +=(pf: PF): Unit =     mapPfs { case pfs => (Some(pfs :+ pf), ()) }    def result(): PF =     mapPfs { case pfs => (None, pfs.foldLeft[PF](Map.empty) { _ orElse _ }) } }  trait ComposableActor extends Actor {   protected lazy val receiveBuilder = new PartialFunctionBuilder[Any, Unit]   final def receive = receiveBuilder.result() } 

Then the behaviors you want to be able to compose into actors:

trait PubSubActor { self:ComposableActor =>   receiveBuilder += {     case Subscribe(topic) => /* ... */     case Publish(topic, msg) => /* ... */   } }  trait MyActor  { self:ComposableActor =>   receiveBuilder += {     case SomeMessage(a, b, c) => /* ... */   } } 

And lastly, an actual actor that uses these composable behaviors:

class MyActorImpl extends ComposableActor with PubSubActor with MyActor 
 
 
     
     
2
 
vote

Pruébalo al revés:

  object Subscription {   case object Subscribe   case object Unsubscribe }  trait Subscription {   this: Actor =>    import Subscription._    var subscribers = Set.empty[ActorRef]    def receive: Receive = {     case Subscribe => subscribers += sender     case Unsubscribe => subscribers -= sender   } }  class MyActor extends Actor with Subscription {   def receive = super.receive orElse {      case msg => // handle msg   } }   

Tenga en cuenta que esto todavía hace uso del patrón de rasgo apilable, que está oculto por el hecho de que he omitido el núcleo. Así que algo como esto todavía funcionaría (al menos creo que lo haré, ATM no tengo tiempo para comprobar si se compila).

  class Core extends Actor {   def receive = Actor.emptyBehavior }  class MyActor extends Core with Subscription   

Por cierto, puede leer más sobre el patrón (no relacionado con los actores) aquí .

 

Try it the other way around:

object Subscription {   case object Subscribe   case object Unsubscribe }  trait Subscription {   this: Actor =>    import Subscription._    var subscribers = Set.empty[ActorRef]    def receive: Receive = {     case Subscribe => subscribers += sender     case Unsubscribe => subscribers -= sender   } }  class MyActor extends Actor with Subscription {   def receive = super.receive orElse {      case msg => // handle msg   } } 

Note that this still makes use of the stackable trait pattern, which is hidden by the fact that I've omitted the core. So something like this would still work (at least I think I will, ATM I have no time to check if it compiles).

class Core extends Actor {   def receive = Actor.emptyBehavior }  class MyActor extends Core with Subscription 

BTW, you can read more about the pattern (not related to Actors) here.

 
 
1
 
vote

para el primero, disculpe por mi inglés Creo que el punto es que el modificador de anulación abstracto requiere la presencia de la implementación concreta del método de recepción, pero en la primera construcción

  class MyActor extends Actor with PubSubActor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */  }}   

no se hace

La razón es que el compilador Scala hace linealización para la herencia Así que en la cadena de métodos de Recepción tenemos la siguiente secuencia:

   1)  override def receive = {         case SomeMessage(a, b, c) => /* ... */       }  2) abstract override def receive = super.receive orElse {         case Subscribe(topic) => /* ... */         case Publish(topic, msg) => /* ... */       }   3) then Actor.receive - it hasn't an implementation   

SO Pubsubactor.Receive no se puede llamar porque usa super.Receive, En su turno, Super.Receive se basa en el actor. Recibe, pero actor. Recibe no ha implementado.

en la segunda construcción

  class MyActor extends Actor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */   }}  class MyActorImpl extends MyActor with PubSubActor   

Tenemos la cadena de métodos de recibir

1)

  abstract override def receive = super.receive orElse {    case Subscribe(topic) => /* ... */    case Publish(topic, msg) => /* ... */ }   

2)

  override def receive = {    case SomeMessage(a, b, c) => /* ... */ }   

3) entonces actor.recuencia: no ha implementado

SO Pubsubactor.Receive puede llamar con éxito Super.Receive

Información adicional:

rasgos apilables

Especificación del idioma Scala, consulte 5.1.2

 

For the first, excuse me for my English I think the point is that abstract override modifier requires presence of concrete implementation of receive method but in the first construction

class MyActor extends Actor with PubSubActor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */  }} 

it is not done

The reason is that scala compiler makes linearization for inheritance so in receive's method chain we have the following sequence:

 1)  override def receive = {         case SomeMessage(a, b, c) => /* ... */       }  2) abstract override def receive = super.receive orElse {         case Subscribe(topic) => /* ... */         case Publish(topic, msg) => /* ... */       }   3) then Actor.receive - it hasn't an implementation 

So PubSubActor.receive cannot be called because it use super.receive, in its turn super.receive relies on Actor.receive, but Actor.receive hasn't an implementation.

In the second construction

class MyActor extends Actor {   override def receive = {     case SomeMessage(a, b, c) => /* ... */   }}  class MyActorImpl extends MyActor with PubSubActor 

we have receive's method chain

1)

abstract override def receive = super.receive orElse {    case Subscribe(topic) => /* ... */    case Publish(topic, msg) => /* ... */ } 

2)

override def receive = {    case SomeMessage(a, b, c) => /* ... */ } 

3) then Actor.receive - it hasn't an implementation

So PubSubActor.receive can successfully call super.receive

Additional info:

Stackable traits

Scala language specification, see 5.1.2

 
 

Relacionados problema

6  Creación de mutadores nombrados dinámicamente en modelos Laravel elocuentes  ( Creating dynamically named mutators in laravel eloquent models ) 
Tengo una lista de campos de fecha, y todos ellos tienen la misma lógica en sus mutadores. Me gustaría extraer esta funcionalidad a un rasgo para que, en el f...

0  Llamando el método de superclase de un rasgo de un objeto no relacionado  ( Calling a traits superclass method from an unrelated object ) 
En la actualidad tenemos docenas de rasgos que contienen el siguiente método: trait ThisTrait extends SuperTrait { override def getList: List[String] = ...

5  Implementar FMT :: PANTALLA PARA VEC <T>  ( Implement fmtdisplay for vect ) 
Quiero implementar el fmt::Display para una estructura anidada comúnmente utilizada en mi código. // The root structure pub struct WhisperFile<'a> { ...

5  Reutilización de herencia y código en rasgos apilables  ( Inheritance and code reuse in stackable traits ) 
En este experimento simplificado, quiero poder construir rápidamente una clase con rasgos apilables que puedan informar sobre qué rasgos se utilizaron para co...

2  Anulando un rasgo y tonta  ( Overriding a trait and selftype ) 
Quiero anular el rasgo escalado BeForEanDaftereach para que las cosas implementen una vez para todas mis pruebas. Finalmente lo conseguí para compilar, pero n...

0  Implementación general de rasgos básicos restringidos por un rasgo público definido localmente  ( Blanket implementation of core traits constrained by locally defined public trai ) 
Tengo el siguiente código: pub trait GetIdentifier { //... } impl<T: GetIdentifier> Hash for T { fn hash(&self) -> //.... } Obtengo el siguien...

7  ¿Cómo puedo hacer que mis propios métodos adaptadores puedan consumir un objeto de rasgo?  ( How do i make my own adapter methods able to consume a trait object ) 
Tengo un rasgo que tiene "métodos adaptadores" que consumen el método: struct Bar<T>(T); trait Foo { fn make_bar(self) -> Bar<Self> where ...

0  ¿Cómo mezclar un código de tiempo de construcción a una clase con un rasgo en Scala?  ( How to mix in a construction time code to a class with a trait in scala ) 
Quiero todas las clases que extienden el rasgo para almacenar su hora de creación (como una instancia DataBaseHelper dbHelper = new DataBaseHelper(context); ...

-1  ¿Es mejor devolver por valor para pequeños tipos para obtener los mejores rasgos?  ( Is it better to return by value for small types for getters in traits ) 
Para la mayoría de los tipos de datos, sigo la convención en https://stackoverflow.com/a/35391084/11963778 y tenga getters que regresan referencias: trai...

1  problema clone_ptr, necesito crear un objeto de copia usando una función de la biblioteca en lugar de nuevo  ( Clone ptr problem i need to create a copy object using a function of the librar ) 
Soy un poco nuevo en plantillas en C ++, así que perdóname si esta pregunta es confusa o estúpida, solo tengo un problema en el que quiero implementar un punt...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos