在“rubymonk”和其他一些ruby资源中,提到当你在一个对象上定义一个单例方法时,Ruby会将这个新方法添加到对象的元类中。对?还有一个访问元类的技巧,就是它:
class Object
def metaclass
class << self
self
end
end
end
foo = "I'm a string object"
def foo.shout
puts self.upcase
end
foo.shout
p foo.metaclass.class
p foo.class.instance_methods.include? :shout
p foo.metaclass.instance_methods.include? :shout
正如我们所料,结果是:
I'M A STRING OBJECT
Class
false
true
一切都好。但是如果我们更改元类方法以返回Hash
而不是self
呢?
class Object
def metaclass
class << self
Hash
end
end
end
然后我们检查这些事情:
p foo.class.instance_methods.include? :shout
p foo.metaclass.instance_methods.include? :shout
p String.instance_methods.include? :shout
p Object.instance_methods.include? :shout
p Hash.instance_methods.include? :shout
是的,所有这些都是假的:
false
false
false
false
false
问题是,shout
方法现在属于什么?它不是元类。那是什么?!
答案 0 :(得分:1)
仍然是元类,你刚刚删除了直接访问它的能力......
foo.instance_eval { class << self; self; end.instance_methods.include?(:shout) }
=> true
答案 1 :(得分:1)
shout
仍然属于元类,你甚至没有失去访问元类的能力(正如其他答案所暗示的那样)。您刚刚在名为Object
的{{1}}上创建了一个无用的方法。这并不能阻止你做以下事情:
metaclass
请注意, (class << any_object_here; self; end)
语法是核心Ruby语法,只能通过重新定义方法来“更改”。
答案 2 :(得分:0)
shout
方法仍然属于foo
的元类,您只是无权访问它,因为您选择始终从方法返回Hash
。 foo.shout
的方法定义不受metaclass
方法语义的影响。