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

chalvern · 2017年04月12日 · 最后由 chalvern 回复于 2017年04月16日 · 1939 次阅读

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()"

学习了,这块确实很绕。

BasicObject 在哪里?

googya 回复

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

liangfeng 回复

嗯嗯,确实有点绕的。

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