2011-03-11 42 views
3

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") 

回答

7

是的。如果一个对象不回复短信,红宝石将发送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 
-2
class Test 
    def say 
    puts "hi" 
    end 
end 

,您可以通过

obj = Test.new 
obj.send "say" 

调用说的方法,并检查使用

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

最后,拼凑所有

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

-1这东西完全无关。再次阅读问题。 – delnan 2011-03-11 13:46:32

+0

啊,我的坏..误读了这个问题.. :( – RameshVel 2011-03-11 14:02:42

2

IIRC,你可以在宝石类定义了method_missing方法来处理这个问题。对不起,我无法提供具体信息。

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