2012-11-19 38 views
2

尽管多次尝试,我无法使用define_method()创建一个方法并提供一个方法。使用define_method和下面的ruby文档

如果我的理解是可以在这里找到http://www.ruby-doc.org/core-1.9.3/Module.html的模块类的文档,我应该能够做到以下任一操作:

define_method(符号,法)→NEW_METHOD

define_method(符号) {块}→PROC

我能够使用define_method(符号){块}但是我收到似乎是一个方法(而不是在文档概述了一个进程我挂):

class M 
    define_method(:hello) { puts "Hello World!"} 
end 

M.new.hello 

我在这里的两个问题是: 1.做上述我似乎并没有收到一个proc,尽管文档清楚地说明这就是我会得到的。 2.我不知道如何提供一个“define_method(符号,方法)→new_method”的方法,我试过Google搜索无济于事,不知道如何使用这种形式的define_method。

如果任何人可以请摆脱这一点,将不胜感激! :) 非常感谢!

+0

你可以发布你实际想要做的事吗?从你发布的小代码中确实不清楚。 – meagar

+0

对我来说(1.9.3p194),运行'define_method(:foo){puts“foo”}'会返回一个proc:'=>#' – pje

+0

I我只跟随rubymonk.com,这被证明是一个很好的资源,只是想了解我自己的关于define_method()和method()的更多信息,因为我不确定我是否理解文档,似乎define_method既可以定义一个实例方法,但仍然返回 – dreamwalker

回答

0

define_method确实会根据使用情况返回ProcMethod

在第一种情况中,Proc返回:

class Test 
    x = define_method :test_method { nil } 
    puts x.inspect 
end 


Test.new.test_method 

运行上面上的控制台输出:

#<Proc:[email protected]:3 (lambda)> 

第二种情况返回UnboundMethod,这是一种类型Method

class Test2 < Test 
    y = define_method :test_method2, Test.instance_method(:test_method) 
    puts y.inspect 
end 

Test2.new.test_method2 

上述输出

#<UnboundMethod: Test#test_method> 

这是一个极其人为的例子,并且限定的方法传递给define_method不是在这种情况下非常有用,我也不能认为哪里会的情况。

+0

当我运行第一个代码示例我得到语法错误,意想不到的'{',期待keyword_end和一些奇怪的原因,我需要把:test_method放在括号中,无论如何,thx很多,这是很大的帮助:D,从来没有想过调用Class_name.new实际上执行被类绑定的代码,并因此使x.inspect得到执行(现在从Module继承的类开始使整体更有意义:) ),一个proc被返回我仍然可以调用Test.new.test_method ... mhmmm相当了不起:) – dreamwalker

0

你可以在你的类中定义这样的方法做到这一点:

class TestClass 
    def a_method 
    end 
    # Store the method in a class variable; define_method is a Module 
    # method and needs to be called from within this context 
    @@x = define_method(:another_method, TestClass.new.method(:a_method)) 
    def x 
    @@x 
    end 

    # And to get a block... 
    @@y = define_method(:yet_another_method) {} 
    def y 
    @@y 
    end 
end 

调用x方法,你会得到这样的事情:

TestClass.new.x 
#<Method: TestClass#a_method> 

,而调用y方法,你能得到像这样的东西:

TestClass.new.y 
#<Proc:[email protected](irb):75 (lambda)> 

这里比较棘手的部分是,您需要一个来自同一类(或超类)的对象的方法,您正在执行define_method,否则它不起作用。举例来说,如果你更换@@x行:

... 
@@x = define_method(:another_method, String.new.method(:gsub)) 
... 

因为TestClass得到以下TypeError不是String一个子类:

TypeError: bind argument must be a subclass of String 

观察,这工作:

... 
@@x = define_method(:another_method, Object.new.method(:object_id)) 
... 

输出与此类似:

TestClass.new.x 
#<Method: Object(Kernel)#object_id> 

我认为背后需要一个方法来自同一类层次的原因是执行面向对象的代码封装和隐私(否则,您可以通过从另一个类传递一个方法来访问私有方法和变量)。