2017-04-20 80 views
2

我想動態調用實例方法。我發現send,call,eval要做到這一點。有些動態調用類方法的例子,但我還沒有想出如何使它適用於實例方法。ruby​​ - 如何動態調用模塊中的實例方法

例如

module MyModule 
    def Foo 
    puts "hello" 
    end 
end 

的實例方法名稱可以由上市:

MyModule.instance_methods 
#=> [:Foo] 

但我無法弄清楚如何調用該方法:

MyModule.send("Foo") 
#=> NoMethodError: undefined method `Foo' for MyModule:Module 

MyModule.method("Foo").call 
#=> NameError: undefined method `Foo' for class `Module' 

eval 'MyModule.Foo' 
#=> NoMethodError: undefined method `Foo' for MyModule:Module 

我如何可以調用實例方法,如Foo,方法名稱?

+1

請注意''eval'MyModule.Foo''是一樣的'MyModule.Foo'。 – Stefan

+4

這是一個*實例方法*。你需要一個實例。 –

回答

9

免責聲明:壞的做法,這讓幾乎沒有任何意義:

MyModule.instance_method(:Foo) # #<UnboundMethod: MyModule#Foo> 
     .bind(Object)   # #<Method: MyModule#Foo> 
     .call     #=> hello 

你不能調用未綁定方法,所以你必須首先將其綁定到某個對象。

參考文獻:


,如果你做的方法單方法這會容易得多:

module MyModule 
    def self.Foo 
    puts "hello" 
    end 
end 

MyModule.Foo 
#=> "hello" 

另一種選擇是使用module_function(使用此選項時,在方法的爲包括對象的可視讀了):

module MyModule 
    def Foo 
    puts "hello" 
    end 
    module_function :Foo 
end 

MyModule.Foo 
#=> "hello" 

而另一個人使用extend self

module MyModule 
    def Foo 
    puts "hello" 
    end 

    extend self 
end 

MyModule.Foo 
#=> "hello" 

PS在方法名稱中使用大寫字母並不常見。這是非常罕見的情況下,在紅寶石可以使用,你的情況是100%不是一個:)

+2

這裏'module_function'和'extend self'都值得一提。 – mudasobwa

+0

非常感謝!單身方法的方法適合我! – jerry

+1

沒有模塊體編輯'Class.new.include(MyModule).new.Foo'就像醜陋,但仍然可能的方式。 – Ilya

相關問題