让ruby对象响应任意消息?

时间:2011-03-11 13:37:47

标签: ruby

ruby​​中是否有等效的python __getattr__(至少可以找到方法)?

class X(object):
    def __getattr__(self, name):
        return lambda x: print("Calling " + name + ": " + x)

x = X()
x.some_method("some args")

所以它可能是这样的:

class X
    # .. ??? ..
    def default_action(method_name, x)
        puts "Calling {method_name}: {x}"
    end
end

x = X.new()
x.some_method("some args")

4 个答案:

答案 0 :(得分:7)

是。如果一个对象没有响应消息,Ruby会发送一条带有消息选择器的method_missing消息和接收者的参数:

class X
  def method_missing(selector, *args, &blk)
    puts "The message was #{selector.inspect}."
    puts "The arguments were #{args.map(&:inspect).join(', ')}."
    puts "And there was #{blk ? 'a' : 'no'} block."
    super
  end
end

x = X.new
x.some_method('some args', :some_other_args, 42)
# The message was :some_method.
# The arguments were "some args", :some_other_args, 42.
# And there was no block.
# NoMethodError: undefined method `some_method'

x.some_other_method do end
# The message was :some_other_method.
# The arguments were .
# And there was a block.
# NoMethodError: undefined method `some_other_method'

请注意,如果您定义method_missing,则还应相应地定义respond_to_missing?。否则你会得到这样的奇怪行为:

x.respond_to?(:foo) # => false
x.foo               # Works. Huh?

在这种特殊情况下,我们处理所有消息,因此我们可以简单地定义如下:

class X; def respond_to_missing?(*) true end end

x.respond_to?(:foo) # => true

答案 1 :(得分:5)

class X
  def method_missing(sym,*args)
    puts "Method #{sym} called with #{args}"
  end
end
a = X.new
a.blah("hello","world")

#=> Method blah called with ["hello", "world"]

答案 2 :(得分:2)

IIRC,你可以在ruby类中定义method_missing来处理这个问题。很抱歉,我无法提供具体信息。

答案 3 :(得分:-2)

class Test
  def say
     puts "hi"
  end
end

你可以通过

调用say方法
obj = Test.new
obj.send "say"

并使用

检查方法可用性
obj.respond_to? "say"

最后,整理所有

if (obj.respond_to? "say")
  obj.send "say"
end