Oop Smalltalk中的消息转发

Oop Smalltalk中的消息转发,oop,smalltalk,abstraction,squeak,Oop,Smalltalk,Abstraction,Squeak,因此,我正在编写一个应用程序,其中一个对象有一组委托对象,它将消息转发给这些对象。我的想法是我可以说 someObject sendMessage:aMessage 并且aMessage将被发送到someObject的所有委托(对于aMessage的任何值)。我能做到这一点的唯一方法是: sendMessage:aMessage | sel chunks kwords arglist msg | chunks := aMessage findTokens:' '. kwords := Arr

因此,我正在编写一个应用程序,其中一个对象有一组委托对象,它将消息转发给这些对象。我的想法是我可以说

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].
MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]
MyobjectClass>>SendMessage: aMessage

   self doSomethingUsefulOnThisInstanceIfApplicable: aMessage.
   self dependents do: [:ea | ea SendMessage: aMessage ] .
这是可行的,但必须有更好的办法。这个解决方案将参数限制为字符串,而且非常难看。有人知道一种更干净、更好的转发消息的方法吗

顺便说一句,我使用的是squeak,但更倾向于独立于实现的解决方案;)

编辑:我应该补充一点,委托与对象属于同一类,因此我不能仅覆盖DoesNotUnderstand:。

尝试实现此功能(它将只转发具有委托的对象不理解的消息):

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

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

为什么不简单地使用多态性,也就是说,在您调用的每个对象的类中实现这个方法呢?然后使用相同的名称在对象方法中实现,该方法仅将调用委托给所有子对象。比如:

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].
MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]
MyobjectClass>>SendMessage: aMessage

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

在不知道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].
MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]
MyobjectClass>>SendMessage: aMessage

   self doSomethingUsefulOnThisInstanceIfApplicable: aMessage.
   self dependents do: [:ea | ea SendMessage: aMessage ] .
您可能还想看看是否可以使用以下任何消息:(这些来自Cincom VisualWORKS)


由于要将对象作为参数传入,因此必须使用如下消息模式将其作为单独的列表传入:

someObject sendMessage:带参数的选择器:argumentList

然后您将使用参数实现#sendMessage:as:

sendMessage:带参数的选择器:argumentList

代表需要:[:del| del perform:a带参数的选择器::argumentList]

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

|论据|

参数:=数组 with:objectnew 随附:1234.5 带:('key'->'value')

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


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

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

谢谢您的建议,但该对象与代理的类型相同,因此我不能这样做。我在原来的问题中添加了这一点。也许您可以为这个委托集合创建一个新类,然后使用doesNotUnderstand?如果不进行更显式的消息创建,这可能是最简单的方法。这将不起作用,因为(如稍后的编辑中所述)对象与其委托属于同一类。