class_eval
和的区别instance_eval
见动态创建类方法
class A; end
A.class_eval do
attr_accessor :x
def barx; end
define_method :foox do; end
end
print 'A.instance_methods : '; p A.instance_methods(false).sort
print 'A.singleton_methods : '; p A.singleton_methods
class B; end
B.instance_eval do
attr_accessor :y
def bary; end
define_method :fooy do; end
end
print 'B.instance_methods : '; p B.instance_methods(false).sort
print 'B.singleton_methods : '; p B.singleton_methods
class C; end
singleton_class = class << C; self end
singleton_class.instance_eval do
attr_accessor :z
def barz; puts 'where is barz ?' end
define_method :fooz do; end
end
print 'C.instance_methods : '; p C.instance_methods(false).sort
print 'C.singleton_methods : '; p C.singleton_methods
print 'singleton_class.barz : '; singleton_class.barz
print 'singleton_class.methods : '; p singleton_class.methods(false)
输出(红宝石 1.8.6):
A.instance_methods : ["barx", "foox", "x", "x="]
A.singleton_methods : []
B.instance_methods : ["fooy", "y", "y="]
B.singleton_methods : ["bary"]
C.instance_methods : []
C.singleton_methods : ["z", "z=", "fooz"]
singleton_class.barz : where is barz ?
singleton_class.methods : ["barz"]
正如您在 B 中看到的那样,尽管 instance_eval 通常创建单例方法,但显然attr_accessor
并define_method
强制定义实例方法。