Smalltalk中的消息转发

时间:2009-05-19 18:31:17

标签: oop smalltalk abstraction squeak

所以我正在编写一个应用程序,其中一个对象有一堆转发消息的委托对象。这个想法是我可以说

someObject sendMessage:aMessage

和aMessage将被发送到someObject的所有委托(对于任何aMessage值)。我能够做到这一点的唯一方法是:

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].

它有效,但必须有更好的方法。这个解决方案将参数限制为字符串,并且只是简单的丑陋。有谁知道更清晰,更好的转发消息的方式?

BTW,我正在使用吱吱声,但是首选的是独立于实现的解决方案;)

编辑:我应该补充一下,委托与对象属于同一个类,所以我不能只重写DoesNotUnderstand:。

5 个答案:

答案 0 :(得分:7)

由于您希望将对象作为参数传递,因此您必须将它们作为单独的列表使用消息模式传递,如下所示:

  

someObject sendMessage:aSelector withArguments:argumentList

然后你实现#sendMessage:withArguments:as:

  

sendMessage:aSelector withArguments:argumentList

     

代表做:[:del |     del perform:aSelector withArguments :: argumentList]。

你可以使用真实对象作为args转发任意复杂的消息:

  

|参数|

     

参数:=数组      with:对象新      与:1234.5      with :('key' - >'value')。

     

someObject sendMessage:#foo:bar:baz:withArguments:arguments

我认为这对大多数方言都是可移植的......

答案 1 :(得分:2)

尝试实现此功能(它只会转发拥有代理人的对象无法理解的消息):

doesNotUnderstand: aMessage 
    delegates
        do: [:delegate | aMessage sendTo: delegate]

您可以显式构造Message对象,如:

msg := Message selector: #foo arguments: #(bar baz)
"then use them like:"
anObject perform: msg selector with: msg arguments

答案 2 :(得分:2)

在Squeak中,请参阅ObjectTracer类。您可以使用它来拦截发送给Object的所有消息。

答案 3 :(得分:1)

好吧,不知道aMessage是什么,并且既然你提到你所有的委托对象属于同一个类,我会做类似的事情:

MyobjectClass>>SendMessage: aMessage

   self doSomethingUsefulOnThisInstanceIfApplicable: aMessage.
   self dependents do: [:ea | ea SendMessage: aMessage ] .

您可能还想查看以下任何消息是否适用于您:(这些来自Cincom VisualWORKS)

update: 
update:with:
update:with:from:

答案 4 :(得分:0)

为什么不简单地使用多态,即在你调用的每个对象的类中实现这个方法?然后使用相同的名称在对象方法中实现,该方法只委托对所有子对象的调用。类似的东西:

MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]