Ruby类和对象

举报
香菜聊游戏 发表于 2021/07/15 00:17:11 2021/07/15
【摘要】   ruby中的对象是类生成的,而类本身也是对象。ruby的顶级类是Object其余所有的类都直接或简介继承与Object。其中Class继承Module,Module继承Object,而所有的对象其实都是Class类的示例,这其中当然包括Object,Module,以及Class类本身。这便产生了一些很有趣的事情,这些等下在慢慢道来。这里先说说ruby内部实现中...

 

ruby中的对象是类生成的,而类本身也是对象。ruby的顶级类是Object其余所有的类都直接或简介继承与Object。其中Class继承ModuleModule继承Object而所有的对象其实都是Class类的示例,这其中当然包括Object,Module,以及Class类本身。这便产生了一些很有趣的事情,这些等下在慢慢道来。这里先说说ruby内部实现中的一些变量,注意类对象与类的对象的区别,类对象指的是类本身因为类也是对象所以称为类对象这是为了区别与普通对象而称呼的,而类的对象是指由这个类所构造出来的对象。

ruby是由c语言实现的且ruby是纯面向对象的语言,在ruby中一切都是对象。在内部实现中ruby任何对象都有以下三个变量:

1.klass指针,因为classruby关键词,所以就变成了klass...。对象中的klass指针指向这个对象所属的类。

2.iv_tbl,是一个保存该对象实例变量的哈希信息。

3.flags,顾名思义这是对象的标志信息变量,用以标志对象是否被污染是否被回收是否被冻结等信息。

如果对象是类(Class)或者是模块(Module(ruby中一切都是对象),除了以上三个变量外,还有以下两个量。

1.super指针,这个一看就知道是指向这个类的父类,有人可能会糊涂,类有父类这没错,模块不能继承难道模块也有父类?的却是有的。模块虽然不可以继承,但一个模块却可以包含(include)另外一个模块。当模块包含一个模块时此模块的super指针就指向被包含模块所生成的虚拟类也或者是说代理类(模块被包含都会生成代理类以便模块插入继承链中)

2.m_tbl,既然上面有个iv_tbl是实例变量表,那么这个肯定是实例方法表。

    由以上信息可知,第一、类跟模块也是对象包含普通对象所有的特征。但类与模块也是特殊的对象,除了普通对象的特征外还有作为类与模块的特别的特征。其次实例变量都是保存在对象自己的数据结构中,而方法都是保存在类中,并且类中保存的方法只有实例方法。那么类方法呢?其实类方法也是实例方法,是类的实例方法,保存在类的单例类中。对象在调用方法时,首先沿着对象klassklass所指的类不一定是直接生成这个对象的类也有可能个是这个对象的单例类)所指的类的方法表中(m_tbl)中寻找方法,若没找到就通过super依次沿着继承链寻找父类跟祖先类的方法表寻找此方法,知道找到所调用的方法或者沿着继承链到Object类。如果在Object中也没有此方法的定义则又从头开始按照上述方法寻找method_missing这个方法。

    继续开头讲得那个有趣的事情。Class是类也是对象Class是本身的对象,Classklass指针指向自己。由上述我们可知方法都是保存在类中的,当Class作为一个对象时他的方法保存在哪里?自然是保存Class对象所属的类中也就是Class类本身当中。但如果Class作为类通过Class.new生存一个普通对象时此时Class类中保存的也还是实例方法。但Class类的类方法呢?按道理Class类方法也就Class这个类对象的实例方法应该保存在Class这个类对象的单例类中。先看一个例子:

我们重新打开Class类定义一个方法


  
  1. class Class
  2. def show
  3. puts "hello"
  4. end
  5. end
  6. lass.new.show
  7. 输出:hello
  8. Class.show
  9. 输出:hello


上述例子Class类中定义的实例方法也成了类方法。为何?其实也不难理解,因为Class做为类时保存类的实例方法,由Class类生成的普通对象即Class.new这个对象的klass指针是指向Class这个类的,根据方法寻找的规则所以Class.new.show是调用Class类的实例方法。而因为Class类也是其本身的对象所以他的klass指针也是指向本身,所以通过Class.show这中方式调用Class类的类方法时还是调用的同一个方法。这一切归根结底是因为类也是对象在作为对象时是与普通对象并无差别,而所谓的类方法其实也是实例方法只不过是另外一个类的实例方法而已。所以Class类是对象还是先是类呢?...

但类对象与普通对象也不是完全是一样的,请看下面例子:

 


  
  1. irb(main):022:0> class Class
  2. irb(main):023:1> @@a="a"
  3. irb(main):024:1> @b="b"
  4. irb(main):025:1> def show
  5. irb(main):026:2> puts @@a
  6. irb(main):027:2> puts @b
  7. irb(main):028:2> end
  8. irb(main):029:1> end
  9. => nil
  10. irb(main):030:0> Class.show
  11. a
  12. b
  13. => nil
  14. irb(main):031:0> Class.new.show
  15. a
  16. > nil



还是重新打开了Class类,只不过在类中定义了两个变量,一个类变量@@a,一个实例变量@b,为何同一个方法却输出不同的结果呢?因为@b是在类域中定义的而不是方法域中定义的所以@bClass类对象的实例变量,所以Class.show能够打印出@b的值,而Class.new.show方法是不能打印出@b的值,因为实例变量保存在对象里其他的任何对象都无法访问到。类变量与类实例变量看起来很相似,但其实是有区别的,它们的区别就是类变量对这个类所生成的所有对象是也可见并且共享的,这也是它们唯一的区别。在类对象本身它们并无二致都可看作类的实例变量。

 

类的真相
实例变量
Ruby中,实例变量是存储在对象中,但是,其于该对象的类没有关系,当给对象的实例变量赋值时,该实例变量就生成了,说白了,实例变量就像是一个挂载在对象上的HashMap,每个对象都可以用自己不同的HashMap,如下例:


  
  1. class Person
  2. def name
  3. @name = "xianlinbox"
  4. end
  5. end
  6. p = Person.new
  7. puts p.instance_variables #==>nil
  8. p.name
  9. puts p.instance_variables #==>@name


方法
作为一个对象,除了有实例变量(也可以称之为属性),还需要有方法。 但是在Ruby中,关于方法的定义并不在对象中,而是在对象自身的类中,这是因为“共享同一个类的对象也必须共享同样的方法”。但是,不能说Class有一个叫做“method”的方法,因为无法使用"Class.method"调用该方法,而要说Class有一个实例方法“method”,这意味着必须创建该类的实例对象,通过实例对象调用该方法。

如果要定义类方法,那么在定义方法的时候,必须加类名前缀,如下


  
  1. class Person
  2. def Person.name
  3. @name = "xianlinbox"
  4. end
  5. end


类本身也是对象
在Ruby中Class本身也是一个对象,关于对象的所有规则都适用于Class.


  
  1. puts "hello".class #=> String
  2. puts String.class #=> Class
  3. puts Class.class #=> Class
  4. puts Class.instance_methods(false) #=> [:superclass,:allocate,:new]
  5. puts Class.instance_variables #=> nil


类的继承体系


  
  1. puts String.superclass #=> Object
  2. puts Class.superclass #=> Module
  3. puts Module.superclass #=> Object
  4. puts Object.superclass #=> BasicObjec
  5. puts BasicObject.superclass #=> nil


 

  • BasicObject是继承体系的根节点。
  • 所有类都继承自Object
  • Class是对Module的继承增强,增加了new()和allocate()方法以创建实例。

文章来源: gamwatcher.blog.csdn.net,作者:香菜聊游戏,版权归原作者所有,如需转载,请联系作者。

原文链接:gamwatcher.blog.csdn.net/article/details/8915670

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。