2010-02-18 139 views
17

如果某个块是闭包,为什么此代码不起作用,以及如何使其工作?关闭不起作用

def R(arg) 
    Class.new do 
    def foo 
     puts arg 
    end 
    end 
end 

class A < R("Hello!") 
end 

A.new.foo #throws undefined local variable or method `arg' for #<A:0x2840538> 
+0

灿我们看到你的错误信息? – samoz 2010-02-18 15:23:16

+0

示例中的错误消息正在评论中。 – yukas 2010-02-18 21:23:21

+0

@Earlz,感谢您的编辑。 – yukas 2010-02-18 21:27:03

回答

26

块关闭,arg确实在Class.new块内可用。这在foo方法中不可用,因为def开始一个新的范围。如果你有define_method,这需要一个块替换def,你会看到你想要的结果:

def R(arg) 
    Class.new do 
     define_method(:foo) do 
      puts arg 
     end 
    end 
end 

class A < R("Hello!") 
end 

A.new.foo # Prints: Hello! 
+0

如何定义一个需要参数的方法? – Geo 2010-02-18 16:54:09

+2

@Geo:使用带参数的块。例如。 'define_method(:add_one)do | x | x + 1结束“ – sepp2k 2010-02-18 16:55:35

5

如果动态地定义类,你可以随意改变它:

def R(arg) 
    c = Class.new 

    # Send the block through as a closure, not as an inline method 
    # definition which interprets variables always as local to the block. 
    c.send(:define_method, :foo) do 
    arg 
    end 

    c 
end 

class A < R("Hello!") 
end 

puts A.new.foo.inspect 
# => "Hello!"