Ruby中,有两个很重要的对象,一个是Class,一个是Object,虽说在ruby中号称“万物皆对象”,但实际上,Object只是Class的一个实例,而Class是一个增强版的Object(因为Class中除了Object所有的属性外,还拥有其他类特有的属性,例如“方法表”。
1.实例所有的非singleton methods方法都保存在类的“方法表”中,所有的singleton methods都保存在实例单例类中,当调用实例的方法时,ruby会首先去查找这个实例的实例单例类,如果这个单例类存在的话,查找这个单例类的方法表,若此方法表中不存在被调用的方法,则去查找实例对应类的方法表(此处假设没有引入module),若还不存在,则顺着继承关系一直向上找,此时,就只找父类本身的方法表,而忽略父类的单例类。
2.类的类方法都保存在类的单例类中(类本身方法表中存放的方法既实例方法仅供object使用),当定义了一个类方法时
- def MyClass.myclass_method
- end
- #或者
- class << MyClass
- def myclass_method
- end
- end
- #或者
- def self.myclass_method
- end
ruby会尝试去创建MyClass这个类的单例类,然后将方法添加到单例类中,如果单例类已经存在,则直接添加到其中,如果其中有同名方法,则直接覆盖。所以,当调用类方法( MyClass.myclass_method)的时候,ruby会直接查找单例类,如果单例类或者类方法不存在,则顺着继承关系向上找,找父类的单例类,以此类推。注意,此时,在单例类中查找的是单例类的“实例方法”(单例类并不能被实例化,类A也不是A的单例类的一个实例,但是,查找的确实是实例方法,和object的查找有些类似,毕竟ruby中,“万物皆对象”)
- class A
- #定义一个类方法,此方法存放在类A的单例类中
- #使用A.class_method_in_singleton_class来调用
- #此处定义类方法的self只是告诉ruby,这是一个类方法,应该放在单例类中
- #所以,如果定义成A.class_method_in_singleton_class效果完全一样
- #并不会因为定义为A.xxx就认为这个方法只是A独有的方法
- def self.class_method_in_singleton_class
- puts self
- end
- end
- #C,注意C本身都没有单例类
- class B < A
- def self.singleton_method_defined_in_B
- end
- end
- class C < B
- end
- #调用类方法,此时ruby查找C的单例类,发现C的单例类不存在
- #顺着继承关系找到B,查找B的单例类,B的单例类存在,查找B的单例类方法表
- #没有找到指定方法,继续爬继承树,找到A
- #查找A的单例类,存在,在A的单例类方法表中查找方法,找到方法
- #注意,此时class_method_in_singleton_class中的self关键字,指的是方法的receiver
- #既C
- C.class_method_in_singleton_class