Inoltro dei messaggi in Smalltalk
-
22-08-2019 - |
Domanda
Quindi sto scrivendo un'applicazione in cui un oggetto ha un gruppo di oggetti delegati a cui inoltra i messaggi.L'idea è che posso dirlo
someObject sendMessage:aMessage
e aMessage verrà inviato a tutti i delegati di someObject (per qualsiasi valore di aMessage).L'unico modo in cui sono stato in grado di farlo è qualcosa del tipo:
sendMessage:aMessage
| sel chunks kwords arglist msg |
chunks := aMessage findTokens:' '.
kwords := Array new:(chunks size).
arglist := Array new:(chunks size).
1 to: (chunks size) do: [:i |
kwords at:i put:((chunks at:i) findTokens:':') at:1.
arglist at:i put:((chunks at:i) findTokens:':') at:2].
sel := ''.
kwords do:[:word | sel := sel,word,':'].
msg := Message selector:sel arguments:arglist.
delegates do:[:del | del perform:msg selector with:msg arguments].
Funziona, ma deve esserci un modo migliore.Questa soluzione limita gli argomenti ad essere stringhe ed è semplicemente brutta.Qualcuno conosce un modo più pulito e migliore per inoltrare i messaggi?
A proposito, sto usando squeak, ma sarebbe preferibile una soluzione indipendente dall'implementazione ;)
MODIFICARE:Dovrei aggiungere che i delegati sono della stessa classe dell'oggetto, quindi non posso semplicemente sovrascrivere DoesNotUnderstand:.
Soluzione
Dal momento che si desidera passare oggetti come argomenti, si dovrà passare loro in un elenco separato di utilizzare un modello di messaggio simile al seguente:
someObject sendMessage: withArguments aSelector: ArgumentList
Poi devi implementare #sendMessage: withArguments: come:
sendMessage: withArguments aSelector: ArgumentList
delegati fanno: [: del | del eseguire: withArguments aSelector::. ArgumentList]
e si sarebbe in grado di inoltrare i messaggi arbitrariamente complesse utilizzando gli oggetti reali come args:
| argomenti |
argomenti: = Array con: nuovo oggetto con: 1234.5 con:. ( 'chiave' -> 'valore')
someObject sendMessage: #foo: bar: baz: withArguments: argomenti
Credo che questo sia portatile per la maggior parte dei dialetti così ...
Altri suggerimenti
Prova a implementarlo (inoltrerà solo i messaggi che non vengono compresi dall'oggetto that ha i delegati):
doesNotUnderstand: aMessage
delegates
do: [:delegate | aMessage sendTo: delegate]
Potresti costruire oggetti Message esplicitamente come:
msg := Message selector: #foo arguments: #(bar baz)
"then use them like:"
anObject perform: msg selector with: msg arguments
In Squeak, vedere l'ObjectTracer di classe. È possibile utilizzarlo per intercettare tutti i messaggi invia a un oggetto.
Bene, senza sapere che cosa è aMessage, e dal momento che lei ha citato tutti gli oggetti sono delegati della stessa classe, mi piacerebbe fare qualcosa di simile:
MyobjectClass>>SendMessage: aMessage
self doSomethingUsefulOnThisInstanceIfApplicable: aMessage.
self dependents do: [:ea | ea SendMessage: aMessage ] .
Si potrebbe anche voler guardare per vedere se si utilizza uno dei seguenti messaggi potrebbe funzionare per voi: (questi sono da Cincom VisualWorks)
update:
update:with:
update:with:from:
Perché non è sufficiente utilizzare un polimorfismo, ovvero, implementare questo metodo nella classe di ogni oggetto che si sta chiamando? Poi si implementa nel metodo oggetto con lo stesso nome, che solo i delegati una chiamata a tutti gli oggetti secondari. Qualcosa di simile:
MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]