Ruby Ruby 类的问题

uestc_bird · 发布于 2016年7月15日 · 最后由 uestc_bird 回复于 2016年7月22日 · 1671 次阅读
96

String.class #=> Class, String是Class类的一个实例; Module.class #=> Class, Module是Class类的一个实例; Class.class #=> Class, Class是Class类的一个实例????

现象一: Class.superclass #=> Module 释义:Class类的父类是Module,既,Class继承于Module,或者说Class类是Module类的子类

现象二: Module.class #=> Class 释义:Module类是Class类的一个实例

鸡生蛋,蛋生鸡问题?一条蟒蛇咬住了自己的尾巴?请指教

补充一点吧:我很想弄清楚这其中的机制,就是how it works?有没有什么书或者资料可以推荐学习一下的(研究源码除外),元编程只是说了现象,没有解释原因。 像C++、python这些语言,有很多的资料可以去了解他们,不仅解释了现象,也解释了现象背后的原因,概念清晰,顺理成章。

共收到 18 条回复
19106
yingce · #1 · 2016年7月15日

推荐你看下Ruby元编程, Class 和 Module 很多东西非常像; 没有你所说的咬尾巴问题

96
uestc_bird · #2 · 2016年7月15日

#1楼 @yingce 就是看了元编程才有那么多疑惑。能具体说一下这本书的那一节解释了这个问题? 面向对象的语言很多,但是从没有遇到过像ruby这样概念模糊的语言,难怪作者自己都说,这门语言的内部非常复杂。。。。。 当然,这很可能是思维被传统面向对象语言固化的原因。 但是搞不清这些基本概念,会很难受的。。。。。

26363
derekyxie · #3 · 2016年7月15日

语言就是这么设计的,javascript里面Function也是这么设计的。 Object.prototype.toString.call(Function)同样也会得到[object Function]

rails toturial里面的ruby章节提到过ruby的class与superclass

96
uestc_bird · #4 · 2016年7月15日

#3楼 @derekyxie how it woks?

19106
yingce · #5 · 2016年7月15日

#2楼 @uestc_bird 我到时觉得我学习Ruby后才理解对象概念 也面向对象更彻底的语言

@derekyxie 看下他推荐的解释

20167
jude · #6 · 2016年7月15日

或许 ruby 对实例、类的定义与其他语言有些区别,其他语言实例跟类是泾渭分明的,但在 ruby ,所有的类都是 Class 的实例,包括 Class 本身,而所有的类都最终继承自 BasicObject (除了 BasicObject 本身)。

用其他语言的逻辑去理解会混乱的,所以我干脆把实例和类当作两个互不相干的维度。 PS. 我觉得要理解这一切最终只能看源码了

96
uestc_bird · #7 · 2016年7月15日

#6楼 @jude 我也是这样想的,估计ruby里面有些概念用传统的OO思想理解是不对的

96
chenjau · #8 · 2016年7月15日

实现的问题只能在 c 源码中得到解释. 要理解这个实现上的技术问题, 只能看源码. 源码包中的 class.c 应该能找到答案.

24405
pinewong · #9 · 2016年7月15日

问题的重点是在: Ruby中Class类的实例(如: Class, String, Module, Array)是一些特殊的对象, 他们也能称作类

正常情况下类的实例都只是单纯的对象, Ruby因为上述特殊的定义变得复杂, 但我们能这么理解上述现象: 现象一: Class.superclass #=> Module 释义: Class类的父类是Module, 既, Class类继承于Module类, 或者说Class类是Module类的子类, 这里Module的概念是类

现象二: Module.class #=> Class 释义: Module类是Class类的一个实例, 这里的Module实际上是对象的角度, 应该理解成: Module对象是Class类的一个实例

总结就是: 这两个现象不能说明咬尾巴, 因为上述问题实际上解释是: Module对象.class.superclass == Module类

至于源码这种复杂特殊关系的实现, 我不清楚. 但我猜想是将Module(其他上述提到特殊的Class类实例对象也是如此)进行了重载, 在重载中赋予了两种身份, 一个是类, 另一个是对象, 两种身份的实现互不干预.

96
uestc_bird · #10 · 2016年7月15日

#9楼 @pinewong 有道理,说得通,不过要想知道底层机制,估计只有去看源码了。

7386
sefier · #11 · 2016年7月17日 2 个赞

#10楼 @uestc_bird 我觉得你如果真的看了《Ruby 元编程》,并且看懂了的话,就不会提这种问题。

里面说的非常清楚,在Ruby里面,类也是实例,是Class类的实例,在Java也是一样,不知道有什么好困惑的。

你的问题用层层递进的三段式就可以回答: 1)Ruby中一切都是对象(object),对象都是类(class)的实例 2)依据第一条,既然一切都是对象(object),那么类(class)同样也是对象,它们都是Class的实例 3)依据第二条,既然类也是对象,那么Class也必须是对象,它是 Class的实例 请注意classClass的大小写不同

你唯一困惑的大概是Class是Class的实例,这个叫“自指”,Java里面也常用,典型的单例模式:

Class MyClass {
  private static MyClass myClass;
  public static MyClass getInstance() {
    if(null == myClass){
      myClass = new MyClass();
    }
    return myClass;
  }
}

在这段代码中,MyClass暂时还不存在,怎么能在自身的代码中生成自己呢?其实就是一个占位功能来自指而已,编译器怎么实现是它自己的事情,你能理解就好了,还用得着看源代码深究?

如果对Ruby元编程其他内容没看懂的,建议看我的另一篇帖子:分析 Ruby 代码的执行环境

96
xiaozhu0827 · #12 · 2016年7月17日

把他全部看成对象就好了啊

96
uestc_bird · #13 · 2016年7月18日

#11楼 @sefier 你的帖子写得不错

96
Ljzn · #14 · 2016年7月18日

String,Module,Class都是类的名字,所以它们都是Class类。这是在下愚见。

96
FrankFang · #15 · 2016年7月19日

如果用JS的机制,是很好理解的。。。 子类跟实例,并不冲突啊

549
lululau · #16 · 2016年7月19日

[15] pry(main)> $ 1.class

From: object.c (C Method):
Owner: Kernel
Visibility: public
Number of lines: 5

VALUE
rb_obj_class(VALUE obj)
{
    return rb_class_real(CLASS_OF(obj));
}
VALUE
rb_class_real(VALUE cl)
{
    while (cl &&
        ((RBASIC(cl)->flags & FL_SINGLETON) || BUILTIN_TYPE(cl) == T_ICLASS)) {
    cl = RCLASS_SUPER(cl);
    }
    return cl;
}
20167
jude · #17 · 2016年7月20日

#7楼 @uestc_bird 有一本书可以解答你的问题 《ruby-under-a-microscope》,你可以看第三章。

简单地讲, ruby 用两种数据结构分别表示对象和类, RObject 表示对象, RClass 表示类, RObject 中有一个 klass 指针指向它的类, RClass 中既有一个 klass 指针指向它的类,也有一个 superclass 指针指向它的超类(这个超类也是用 RClass 来表示)

96
uestc_bird · #18 · 2016年7月22日

#17楼 @jude 这本书早闻大名,正准备开始看,非常好的建议,谢谢!

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