我只是在玩元编程,所以请不要回答使用a
@foo
实例变量。
我有以下尝试记住实例和类方法 通过从正在运行的方法覆盖方法定义..
class Obj
class << self
def meta_me; self; end
def class_memoize
puts "hard core calculating ..."
abc = "huge calculation result"
raise "broken here with infinite loop"
define_class_method "class_memoize" do
puts abc
abc
end
class_memoize
end
def define_class_method name, &blk
meta_me.instance_eval do
define_method name, &blk
end
end
end
def instance_memoize
puts "hard core calculating ..."
abc = "huge calculation result"
self.class.meta_me.send :define_method, :instance_memoize do
puts abc
abc
end
instance_memoize
end
end
o = Obj.new
o.instance_memoize
# hard core calculating ...
# huge calculation result
o.instance_memoize
# huge calculation result
实例版本有效,但类版本没有。
我已经尝试过课程版本以供参考。
答案 0 :(得分:1)
除了道德之外,它比你想象的要容易得多。你的主要问题是你的meta_me方法使用了错误的东西。试试这个:
class Object
def metaclass
class<<self;self;end
end
end
在Ruby中进行元编程时,这是一个相当常见的monkeypatch。现在,动态重新实现方法很容易:
class Obj
def self.class_memoize
puts "calculating..."
abc = "result"
metaclass.send(:define_method, :class_memoize) do
puts abc
abc
end
class_memoize
end
def instance_memoize
puts "calculating..."
abc = "result"
metaclass.send(:define_method, :instance_memoize) do
puts abc
abc
end
instance_memoize
end
end
正如您所看到的,一旦您拥有了元类对象,无论是类方法还是实例方法,重新定义方法都是以相同的方式完成的。请注意,如果您不想使用元类方法来玷污整个命名空间,那么只要您想引用它就可以更好地使用class<<self;self;end
惯用法。您可以直接在其上调用方法,如下所示:
(class<<self;self;end).send(:define_method, :foo){|bar| bar*23}
请注意,parens并不是真正需要的,它只是有助于控制裸元类引用的混乱:)希望这会有所帮助。