我有以下程序。
module C
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def test_for
class_eval <<-DEFINECLASSMETHODS
def self.my_method(param_a)
puts "SELF is: #{self.inspect}"
puts param_a
puts "#{param_a}"
end
DEFINECLASSMETHODS
end
end
end
class A
include C
end
class B < A
test_for
end
当我运行B.new.my_method("aaa")
时,我收到了此错误
NameError: undefined local variable or method `param_a' for B:Class
我很困惑。
我在类方法my_method,
中将param_a定义为局部变量puts param_a
运行良好,并输出“aaa”。
然而,
puts "#{param_a}"
输出该错误。
为什么?
任何人都能解释一下吗?
答案 0 :(得分:3)
你得到那个错误,因为#{}
没有将param_a插入到传递给puts的字符串中 - 它将它插入传递给class_eval的字符串中。它会逃脱它,即
puts "\#{param_a}"
您还可以使用<<-'DEFINECLASSMETHODS'
代替<<-DEFINECLASSMETHODS
在heredoc中禁用插值。这也允许您使用其他元字符而不必转义它们。
答案 1 :(得分:2)
请尝试使用“class_eval do; end”,如下所示:
def test_for
class_eval do
def self.my_method(param_a)
puts "SELF is: #{self.inspect}"
puts param_a
puts "#{param_a}"
end
end
end
这样,不需要代码转义。
答案 2 :(得分:1)
这些是你正在跳过的一些非常复杂的箍,基本上实现了这个:
module C
def test_for
define_singleton_method :my_method do |param_a|
puts "SELF is: #{inspect}"
p param_a
end
end
end
class A
extend C
end
class B < A
test_for
end
B.my_method 'foo'
# => SELF is: B
# => "foo"
编辑:我刚刚意识到上面的解决方案仍然比它需要的复杂得多。事实上,我们根本不需要任何元编程::
module C
module D
def my_method(param_a)
puts "SELF is: #{inspect}"
p param_a
end
end
def test_for
extend D
end
end
class A
extend C
end
class B < A
test_for
end
B.my_method 'foo'
# => SELF is: B
# => "foo"