Smalltalk 中的消息转发

发布于 2024-07-19 17:27:39 字数 872 浏览 5 评论 0原文

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

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,但首选独立于实现的解决方案;)

编辑:我应该补充一点,委托与对象属于同一类,所以我不能只覆盖不明白:。

So I'm writing an application where one object has a bunch of delegate objects that it forwards messages to. The idea is that I can say

someObject sendMessage:aMessage

and aMessage will be sent to all of someObject's delegates (for any value of aMessage). The only way I've been able to do this is something like:

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

It works, but there has to be a better way. This solution limits the arguments to being strings, and is just plain ugly. Does anyone know a cleaner, better way to forward messages?

BTW, I'm using squeak, but an implementation-independent solution would be prefered ;)

EDIT: I should add that the delegates are of the same class as the object, so I can't just override DoesNotUnderstand:.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

神回复 2024-07-26 17:27:39

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

someObject sendMessage: aSelector withArguments: argumentList

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

sendMessage: aSelector withArguments: argumentList

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

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

| 参数 |

参数 := 数组
与:新对象
与:1234.5
与:('键'->'值')。

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

我认为这也可以移植到大多数方言......

Since you want to pass objects in as arguments, you'll have to pass them in as a separate list of using a message pattern like the following:

someObject sendMessage: aSelector withArguments: argumentList

Then you'd implement #sendMessage:withArguments: as:

sendMessage: aSelector withArguments: argumentList

delegates do:[:del |
del perform: aSelector withArguments: :argumentList].

and you'd be able to forward arbitrarily complex messages using real objects as args:

| arguments |

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

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

I think this is portable to most dialects as well...

因为看清所以看轻 2024-07-26 17:27:39

尝试实现这个(它只会转发具有委托的对象无法理解的消息):

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

Try implementing this (it will only forward messages that aren't understood by the object that has the delegates):

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

You could construct Message objects explicitly like:

msg := Message selector: #foo arguments: #(bar baz)
"then use them like:"
anObject perform: msg selector with: msg arguments
染年凉城似染瑾 2024-07-26 17:27:39

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

In Squeak, see the class ObjectTracer. You can use it to intercept all message sends to an Object.

丢了幸福的猪 2024-07-26 17:27:39

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

MyobjectClass>>SendMessage: aMessage

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

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

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

Well, without knowing what aMessage is, and since you mentioned all your delegate objects are of the same class, I'd do something like:

MyobjectClass>>SendMessage: aMessage

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

You may also want to look to see if using any of the following messages could work for you: (these are from Cincom VisualWORKS)

update: 
update:with:
update:with:from:
找回味觉 2024-07-26 17:27:39

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

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

Why not simply use a polymorphism, that is, implement this method in class of each object you are calling? Then you implement in your object method with the same name, which just delegates a call to all subobjects. Something like:

MyObjectClass>>someMethod
subobjects do: [:each | each someMethod]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文