【问题标题】:Message forwarding in SmalltalkSmalltalk 中的消息转发
【发布时间】:2010-10-27 10:16:33
【问题描述】:

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

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

【问题讨论】:

    标签: oop smalltalk abstraction squeak


    【解决方案1】:

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

    someObject sendMessage: aSelector withArguments: argumentList

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

    sendMessage: aSelector withArguments: argumentList

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

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

    |论据 |

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

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

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

    【讨论】:

      【解决方案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
      

      【讨论】:

      • 谢谢你的建议,但是对象和代表是同一类型的,所以我不能这样做。我将其添加到原始问题中。
      • 也许你可以为这个委托集合创建一个新类,然后使用doesNotUnderstand?如果不进行更明确的消息创建,这可能是最直接的方法。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

          • 这不起作用,因为(如稍后编辑中所述)该对象与其委托属于同一类。
          猜你喜欢
          • 1970-01-01
          • 2019-11-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-26
          • 1970-01-01
          • 2013-02-22
          相关资源
          最近更新 更多