我有这个元编程方案,触及Ruby的一些更精细的功能,我不太确定如何解决。
每个人都可以轻松编写下面的示例来执行它应该做的事情,但我需要在超类和派生子类中动态定义方法。
在示例中,基类具有动态定义的方法:foo和cource,它暴露给子类B. 但是,当我在子类B的实例上调用:foo时,我在动态定义的方法中检测到,我似乎无法将它从B类实例传递到A类实例,而cource就是我想要的
wierd ruby的类别定义了子类中的方法,但无论如何,这就是我想要解决的问题。
任何线索?
class A
def self.some_method method,*_params
puts "#{name}: defining #{method}"
define_method method do |*args|
puts "#{self.class.name}: called #{method}"
super *args unless self.class.instance_methods(false).include?(method)
end
end
end
class B < A
end
A.some_method :foo
B.new.foo
输出
A: defining foo
B: called foo
NoMethodError: super: no superclass method `foo' for #<B:0x007f9eab85bfa0>
答案 0 :(得分:3)
我认为你的逻辑存在缺陷。
您可以为超类A
定义动态方法。调用B.new.foo
在B
中找不到任何方法,因此它会继承继承行。它在foo
中找到了A
方法,因此它使用了该方法
这意味着
super *args unless self.class.instance_methods(false).include?(method)
部分根本不需要。
我看到它的方式,经典的方法继承就是你所需要的!
答案 1 :(得分:0)
确实存在缺陷的逻辑。当然需要访问具有定义方法的类,而超级无法帮助你。
以下是解决问题的方法:
class A
def self.some_method method,*_params
puts "#{name}: defining #{method}"
define_method method do |*args|
puts "#{self.class.name}: called #{method}"
klass = self.class
klass = klass.superclass while !klass.instance_methods(false).include?(method)
# klass is now where the instance method is defined
# and you can now access its class variables etc.
puts "#{klass.name}: has method #{method}"
end
end
end
class B < A
end
A.some_method :foo
B.new.foo
输出
A: defining foo
B: called foo
A: has method foo