2

是否可以向对象发送任何内容?

让我详细说明。例如我可以有这样的东西:

val = some_stack.include?(some_val) ? some_val : nil

obj1.obj2.send(val).obj3.obj4

上面的调用不起作用,因为 nil 不是符号。所以解决方案是:

if val.nil?
  obj1.obj2.obj3.obj4
else
  obj1.obj2.send(val).obj3.obj4
end

不过我不太喜欢这个。还有其他方法吗?

4

3 回答 3

5

我不知道有任何方法在self不带任何参数的情况下返回(但我可能忽略了一些东西),但没有理由不能将一个猴子补丁添加到您正在使用的类中:

irb(main)> class Object
irb(main)>   def ignore
irb(main)>     self
irb(main)>   end
irb(main)> end
=> nil
irb(main)> msg = nil
=> nil
irb(main)> 'hi'.send(msg || :ignore).upcase
=> "HI"
irb(main)> msg = :reverse
=> :reverse
irb(main)> 'hi'.send(msg || :ignore).upcase
=> "IH"
于 2010-06-23T17:00:19.317 回答
4

没有内置的方式。您可以执行以下操作:

module Kernel
  def __self__
    self
  end
end

obj1.obj2.send(val || :__self__).obj3.obj4

更神秘:

[:obj1, :obj2, val, :obj3, :obj4].compact.inject(self, :send)
# (assuming that obj1 is a method call like obj2, ...)

但我建议保持简单:

intermediate = obj1.obj2
intermediate = intermediate.some_val if some_stack.include?(some_val)
intermediate.obj3.obj4
于 2010-06-23T17:00:11.330 回答
2

我可能会误解某些东西,但我认为这个问题试图做一些没有意义的事情。

在 Ruby 中,向对象发送消息意味着要求该对象以某种方式响应请求的消息(在本例中使用符号指定)。消息就是我们通常所说的方法调用。在本例中,“send”是发送给对象的消息,接收“send”消息的对象接受传递的参数(另一个方法的符号)并向自身(对象)发送与该方法对应的消息通过符号。

所以发送一个 nil 对象几乎等同于不发送任何东西——除了你实际上已经向对象发送了一条消息,只是一条没有任何内容的消息。所以对象不可避免地会混淆它应该做什么,因为它被告知什么也不做。如果有人要求你什么都不做,你不会也感到困惑吗?:)

所以转向你的具体问题:

重新表述您的问题(要清楚我是否理解),我想您是在问:是否可以链接一系列调用,其中链中的一个调用仅在变量(通过发送消息)是非零的?

也许这对于通用解决方案更好?

obj2 = obj1.obj2
obj2 = obj2.send( val ) if val
obj2.obj3.obj4

否则,要真正回答您的问题(现在确实有意义,但可能会使事情变得更加复杂),您可以将其放入您的课程中:

def send( method, *args )
    super if method
end

或者,您可以这样做:

class Object
    def send( method, *args )
        super if method
    end
end

这将导致每个对象接受 nil (并且悄悄地什么都不做)发送。

此解决方案将引发警告 [原文如此]:

警告:重新定义“发送”可能会导致严重问题

您可以通过重定向 $stderr 来抑制此警告,但它不是线程安全的(Matz 说,来自简短的 Google 搜索)。

于 2010-06-24T07:31:17.070 回答