4

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

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

它有效,但必须有更好的方法。该解决方案将参数限制为字符串,并且非常难看。有谁知道转发消息的更清洁、更好的方法?

顺便说一句,我正在使用 squeak,但最好使用独立于实现的解决方案;)

编辑:我应该补充一点,代表与对象属于同一类,所以我不能只覆盖 DoesNotUnderstand:。

4

5 回答 5

7

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

someObject sendMessage: aSelector withArguments: argumentList

然后你会实现 #sendMessage:withArguments: 为:

sendMessage:aSelector withArguments:argumentList

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

并且您可以使用真实对象作为参数转发任意复杂的消息:

| 论据 |

arguments := Array with: Object new with: 1234.5 with: ('key'->'value')。

someObject sendMessage:#foo:bar:baz:withArguments:参数

我认为这也适用于大多数方言......

于 2009-05-20T01:03:28.697 回答
2

在 Squeak 中,请参见 ObjectTracer 类。您可以使用它来拦截所有发送到对象的消息。

于 2009-05-20T16:33:05.243 回答
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
于 2009-05-19T18:42:35.993 回答
1

好吧,在不知道 aMessage 是什么的情况下,并且由于您提到所有委托对象都属于同一类,因此我会执行以下操作:

MyobjectClass>>SendMessage: aMessage

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

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

update: 
update:with:
update:with:from:
于 2009-05-19T20:18:32.420 回答
0

为什么不简单地使用多态性,即在您调用的每个对象的类中实现此方法?然后你在你的对象方法中实现同名,它只是将调用委托给所有子对象。就像是:

MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]
于 2009-05-19T19:26:39.873 回答