我在模块中动态定义类方法时遇到问题。请参阅下面的代码。尝试引用模块中的另一个类方法时,我得到一个 NameError: undefined local variable or method
。看起来这可能是一个范围或上下文问题,但到目前为止我还没有弄清楚。
module Bar
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def fruits
["apple", "orange", "banana"]
end
def example_function(string)
string.upcase
end
fruits.each do |fruit|
method_name = fruit.to_sym
define_method(method_name) { example_function(fruit) }
end
end
end
class Foo
include Bar
end
puts Foo.apple
puts Foo.orange
puts Foo.banana
我希望能够调用:
puts Foo.apple => "APPLE"
puts Foo.orange => "ORANGE"
puts Foo.banana => "BANANA"
目前,当我尝试其中任何一个时,我都会收到以下错误:
NameError:Bar::ClassMethods:Module 的未定义局部变量或方法“fruits”
此外,Bar::ClassMethods 中的类方法应该对 Foo 可用,所以我应该能够调用:
puts Foo.fruits => ["apple", "orange", "banana"]
要求:
- 所有代码都在一个模块中。
- 该模块允许混合使用实例方法和类方法(见下文)。
- 目标方法是动态定义的。
阅读“Ruby 中的包含与扩展”(尤其是标题为“常见习语”的部分)http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/
非常感谢您的帮助!
最佳答案
问题是,fruits
方法被定义为实例方法,但您在 ClassMethods
上调用它时没有实例。像这样定义它:
def self.fruits
["apple", "orange", "banana"]
end
并且您的代码有效。
编辑:
要使 fruits
方法也作为 Foo
上的类方法可访问,您必须以在内部可访问的方式声明 fruits
数组ClassMethods
模块。一种方法是将数组声明为类变量,并在 fruits
方法和 each
block 中使用它。看下面的代码:
module Bar
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
@@fruits = ["apple", "orange", "banana"]
def fruits
@@fruits
end
def example_function(string)
string.upcase
end
@@fruits.each do |fruit|
method_name = fruit.to_sym
define_method(method_name) { example_function(fruit) }
end
end
end
class Foo
include Bar
end
puts Foo.apple
puts Foo.orange
puts Foo.banana
puts Foo.fruits
关于Ruby:在模块中动态定义类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17600190/