class MyClass def hi 'hi object' end def self.bye 'bye singleton method' end end
对于上述MyClass,也创建了一个元类(比如#MyClass).现在方法’hi’是一个实例级方法,可以在MyClass的所有对象上调用.方法’bye’是MyClass的单例方法,它位于#MyClass中.原因(我想是这样)为什么’嗨’保存在MyClass中,而不是MyClass的所有对象都是因为它避免了冗余.但是我们不能有多个名为MyClass的类.所以为什么不在MyClass中存储’再见’而不是#MyClass,因为我们不能有多个MyClass.我绝对不知道为什么这是它的方式,我只是想了解它背后的原因.
—– UPDATE —-
元类存储类信息,如单例方法等.但是,由于类是一个单例对象(它是类的一个实例,并且它的类型独立),那么为什么不将所有的信息保存在类本身而不是元类.
解决方法
这是一个快速的ruby脚本,解释这个问题:
#!/usr/bin/env ruby puts ObjectSpace.count_objects[:T_CLASS] #>> 471 class X def self.foo end def bar end end puts ObjectSpace.count_objects[:T_CLASS] #>> 473
这就是“ObjectSpace.count_objects [:T_CLASS]将OP计数增加2的意思.”让我们将额外的类称为X的单例类,因为这似乎是Ruby在内部调用的类.
irb> X => X irb> X.singleton_class => <Class: X>
请注意,#foo方法是X.singleton_class的实例方法,而不是X.
irb> X.instance_methods(false) => [:baz] irb> X.singleton_class.instance_methods(false) => [:foo]
那为什么是:foo存储在X.singleton_class而不是X?不会只有一个X吗?
我认为主要原因是一致性.考虑以下简单的实例对象的场景.
car = Car.new def car.go_forth_and_conquer end
正如@mikej高超的解释,这种新方法存储在汽车的单身班.
irb> car.singleton_class.instance_methods(false) => [:go_forth_and_conquer]
类是对象
现在,类也是对象.每个类都是Class的一个实例.因此,当定义一个类(例如X)时,ruby真的创建了一个Class的实例,然后向实例添加方法(类似于上面所提到的方法).例如,这里是另一种创建方式一个新课
Car = Class.new do def go_forth_and_conquer puts "vroom" end end Car.new.go_forth_and_conquer
因此,只需重用代码并以相同的方式进行操作就更容易了(即在X.singleton_class中保留foo).这可能需要较少的工作,并且会导致更少的惊喜,所以没有人会需要编写代码来处理类实例与其他实例不同.
可能不重要
你可能会认为,如果Ruby没有Class类的单例类,那么可以节省一些内存.然而,对我来说,实际存储的是一个实现细节,我们可能不应该指望.只要行为是一致的,Rubinius,MRI和JRuby都可以不同地存储方法和实例.对于我们所知道的,只要总体行为符合ruby规范,就可以合理地实现Ruby,它不会为类对象而急切地创建单例类. (例如,在#singleton_class方法首次被调用之前,实际的单例类不存在)