2017-04-20 66 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

相关问题