2011-03-11 33 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"]