Ruby on Rails Ruby 中 Object 和 Class

MyDataFlow · 发布于 2017年10月06日 · 281 次阅读
96
本帖已被设为精华帖!

Object和Class的关系

Ruby代码注释

Classes, modules, and objects are interrelated. In the diagram
that follows, the vertical arrows represent inheritance, and the
parentheses metaclasses. All metaclasses are instances
of the class `Class'.

                           +---------+             +-...
                           |         |             |
           BasicObject-----|-->(BasicObject)-------|-...
               ^           |         ^             |
               |           |         |             |
            Object---------|----->(Object)---------|-...
               ^           |         ^             |
               |           |         |             |
               +-------+   |         +--------+    |
               |       |   |         |        |    |
               |    Module-|---------|--->(Module)-|-...
               |       ^   |         |        ^    |
               |       |   |         |        |    |
               |     Class-|---------|---->(Class)-|-...
               |       ^   |         |        ^    |
               |       +---+         |        +----+
               |                     |
  obj--->OtherClass---------->(OtherClass)-----------...

简单的说就是垂直的箭头代表的继承关系,而圆括号代表着元类。

我们从这里可以看出来Class是一个Object,当我们用Class.is_a? Object去判断时,也确实返回了true,于此同时我们也可以看到Object的元类是继承于Class的,所以当我们用Object.is_a? Class的时候也是返回了true。

问题出在哪里

看下面一段Rails的代码:

module Kernel
  # class_eval on an object acts like singleton_class.class_eval.
  def class_eval(*args, &block)
    singleton_class.class_eval(*args, &block)
  end
end

它的作用很简单,就是让Class A的实例对象a具备class_eval的能力,也就是说我们具备了下面这种能力

a = A.new
a.class_eval "def hello; puts \"hello from class_eval\"; end;"
a.hello

但是当我们执行下面这段代码的时候,就会告诉我们hello方法没定义

A.class_eval "def hello; puts \"hello from class_eval\"; end;"
A.hello 

这是为什么呢?

当我们对类A执行下面代码

A.is_a? Class => true
A.is_a? Object => true
A.instance_of? Class => true
A.instance_of? Object => false
A.superclass => Object
A.class => Class

就可以看出来,A是Class的实例对象,所以在方法查找的时候,会先从Class及Class的superclass,Module中寻找。

当我们对类A的实例a执行同样的代码

a.is_a? Class => false
a.is_a? Object => true
a.instance_of? Class => false
a.instance_of? Object => false
a.instance_of? A => true
a.class => A

就可以看出来,a是A的实例对象,所以在方法查找的时候,会先从A中寻找相对的方法,当方法在A中不存在的时候,就会去A的superclass中寻找,而A的superclass是Object。

至此这个问题的答案就解开了。

总结

  • 在Ruby中,所有的class声明的类都是Class的实例对象,也就是说class A声明的类A,class为Class,而它的superclass是Object
  • Ruby方法的查找顺序是按照class,class的superclass一直向下找下去的
共收到 0 条回复
84794b DavidAlphaFox 将本帖设为了精华贴 10月06日 21:43
需要 登录/注册 后方可回复, 如果你还没有账号请点击这里 注册