Ruby Ruby 中的衔尾蛇——对象和类之间的循环关系

chalvern · 发布于 2017年04月12日 · 最后由 chalvern 回复于 2017年04月16日 · 503 次阅读
43079a

Ruby中的 ∞

在Ruby中,Object 是所有类的超类 (Superclass) , "Class"是所有对象的类 (class) 。即,对任何类取有限次 superclass ,最后都能得到 Object (其实是BasicObject); 对任何的对象(类也是一种对象)取有限次 class 最后都能得到Class。

相对于其他的编程语言,Ruby这里存在一个比较绕的逻辑,这里先画出基本的关系图如下: image

Object 与 Class 中的方法

由于对象与类之间特殊的关系,那么在方法的角度来分析,能得出什么样好玩的结论呢?

1. Object中的类方法 (methods) 与Class中的实例方法 (instance_methods) 相同

Object.methods == Class.instance_methods
# => true

2. Class中的实例方法 (instance_methods) 一部分继承于Object的实例方法 (instance_methods), 另一部分应该 Mixin 于独立的 模块.

Object.instance_methods.length
# => 56 

(Class.instance_methods-Object.instance_methods).length
# => 44

3. Class中的类方法 (methods) 主要继承于Object的类方法 (methods)

Class.methods-(Object.methods&Class.methods)
# => [:nesting]

从输出的结果来看, Class的类方法主要继承与Object, 但是在此之外添加了一个 :nesting 方法.

4. [基于前两个结论]Class中的类方法与实例方法具有很高的重合性

Class.methods-(Object.methods&Class.instance_methods)
# => [:nesting]

根据个人的理解, Ruby的元编程能力的最本质表现, 是Ruby可以像对待对象 (Object) 那样动态地对类 (Class) 进行运行时编辑. 在代码层面的表达, 则是 类(Class) 能够同时进行两次 new ("Class#new"和"Class#new#new") 分别创建 对象 .

根据上面的结论,可以认为Ruby在设计之初主要问题之一便是统一 对象 (Object) 与 类 (Class) 之间的关系. 而为了赋予Ruby元编程的能力, 设计上无法避免 对象 在方法定义上的冗余问题(比如一些方法同时是 Class 的类函数和实例函数 ), 为了解决这个问题, 就自然而然地引入了 模块 (module) 的概念.

Ruby中方法的调询

在Ruby中,最简单的方法调询路径,是当某个对象调用某个方法时,Ruby会首先到对象所对应的类中查找是否有这个方法。但是因为继承以及混入 (mixin) 的存在, Ruby中存在更为复杂的方法调询路径。

与Java等语言类似,为了调用方法,Ruby会首先查找对象的类,然后依次查找类的超类 (superclass) ,直到找到这个方法为止(当然如果已经找到了 Object 还找不到一般就会报错了)。比如下面的代码:

class MyClass:
  def my_method;
    'my_mythod()'
  end
end

class MySubclass < MyClass
end

obj = MySubclass.new
obj.my_method()     # => "my_method()"
共收到 4 条回复
96

学习了,这块确实很绕。

60

BasicObject 在哪里?

43079a
60googya 回复

BasicObject在Object的上面,不过它很特殊,为了避免混淆视听,所以没有画出来。。。😅

43079a
32liangfeng 回复

嗯嗯,确实有点绕的。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册