最近使用开发的过程中出现了一个小问题,顺便记录一下原因和方法--方法模块
ruby中的对象是类生成的,而类本身也是对象。ruby的顶级类是Object其余所有的类都直接或简介继承与Object。其中Class继承Module,Module继承Object,而所有的对象其实都是Class类的示例,这其中当然包括Object,Module,以及Class类本身。这便产生了一些很风趣的事件,这些等下在慢慢道来。这里先说说ruby内部实现中的一些变量,注意类对象与类的对象的区别,类对象指的是类本身因为类也是对象所以称为类对象这是为了区别与一般对象而称谓的,而类的对象是指由这个类所结构出来的对象。
ruby是由c语言实现的且ruby是纯面向对象的语言,在ruby中一切都是对象。在内部实现中ruby任何对象都有以下三个变量:
1.klass指针,因为class是ruby关键词,所以就变成了klass...。对象中的klass指针指向这个对象所属的类。
2.iv_tbl,是一个保存该对象实例变量的哈希信息。
3.flags,望文生义这是对象的标志信息变量,用以标志对象是不是被污染是不是被回收是不是被冻结等信息。
如果对象是类(Class)或者是模块(Module)(ruby中一切都是对象),除了以上三个变量外,还有以下两个量。
1.super指针,这个一看就知道是指向这个类的父类,有人可能会糊涂,类有父类这没错,模块不能继承难道模块也有父类?的倒是有的。模块虽然不可以继承,但一个模块却可以包括(include)另外一个模块。当模块包括一个模块时此模块的super指针就指向被包括模块所生成的虚拟类也或者是说代理类(模块被包括都会生成代理类以便模块插入继承链中)
2.m_tbl,既然上面有个iv_tbl是实例变量表,那么这个肯定是实例方法表。
由以上信息可知,第一、类跟模块也是对象包括一般对象所有的特征。但类与模块也是特别的对象,除了一般对象的特征外还有作为类与模块的特别的特征。其次实例变量都是保存在对象自己的数据结构中,而方法都是保存在类中,并且类中保存的方法只有实例方法。那么类方法呢?其实类方法也是实例方法,是类的实例方法,保存在类的单例类中。对象在调用方法时,首先沿着对象klass(klass所指的类纷歧定是直接生成这个对象的类也有可能个是这个对象的单例类)所指的类的方法表中(m_tbl)中寻觅方法,若没找到就通过super顺次沿着继承链寻觅父类跟祖先类的方法表寻觅此方法,知道找到所调用的方法或者沿着继承链到Object类。如果在Object中也没有此方法的定义则又从头开始按照上述方法寻觅method_missing这个方法。
继承开头讲得那个风趣的事件。Class是类也是对象Class是本身的对象,Class的klass指针指向自己。由上述我们可知方法都是保存在类中的,当Class作为一个对象时他的方法保存在哪里?自然是保存Class对象所属的类中也就是Class类本身当中。但如果Class作为类通过Class.new生活一个一般对象时此时Class类中保存的也还是实例方法。但Class类的类方法呢?按情理Class类方法也就Class这个类对象的实例方法应该保存在Class这个类对象的单例类中。先看一个例子:
我们从新打开Class类定义一个方法
class Class def show puts "hello" end end lass.new.show 输出:hello Class.show 输出:hello
上述例子Class类中定义的实例方法也成了类方法。为何?其实也不难理解,因为Class做为类时保存类的实例方法,由Class类生成的一般对象即Class.new这个对象的klass指针是指向Class这个类的,根据方法寻觅的规矩所以Class.new.show是调用Class类的实例方法。而因为Class类也是其本身的对象所以他的klass指针也是指向本身,所以通过Class.show这中方法调用Class类的类方法时还是调用的同一个方法。这一切归根结底是因为类也是对象在作为对象时是与一般对象并无差别,而所谓的类方法其实也是实例方法只不过是另外一个类的实例方法而已。所以Class类是对象还是先是类呢?...
但类对象与一般对象也不是完全是一样的,请看下面例子:
irb(main):022:0> class Class irb(main):023:1> @@a="a" irb(main):024:1> @b="b" irb(main):025:1> def show irb(main):026:2> puts @@a irb(main):027:2> puts @b irb(main):028:2> end irb(main):029:1> end => nil irb(main):030:0> Class.show a b => nil irb(main):031:0> Class.new.show a > nil
还是从新打开了Class类,只不过在类中定义了两个变量,一个类变量@@a,一个实例变量@b,为何同一个方法却输出不同的结果呢?因为@b是在类域中定义的而不是方法域中定义的所以@b是Class类对象的实例变量,所以Class.show能够打印出@b的值,而Class.new.show方法是不能打印出@b的值,因为实例变量保存在对象里其他的任何对象都没法访问到。类变量与类实例变量看起来很相似,但其实是有区别的,它们的区别就是类变量对这个类所生成的所有对象是也可见并且共享的,这也是它们唯一的区别。在类对象本身它们并无二致都可看做类的实例变量。
类的本相
实例变量
在Ruby中,实例变量是存储在对象中,但是,其于该对象的类没有关系,当给对象的实例变量赋值时,该实例变量就生成了,说白了,实例变量就像是一个挂载在对象上的HashMap,每个对象都可以用自己不同的HashMap,如下例:
class Person def name @name = "xianlinbox" end end p = Person.new puts p.instance_variables #==>nil p.name puts p.instance_variables #==>@name
方法
作为一个对象,除了有实例变量(也可以称之为属性),还需要有方法。 但是在Ruby中,关于方法的定义并不在对象中,而是在对象自身的类中,这是因为“共享同一个类的对象也必须共享一样的方法”。但是,不能说Class有一个叫做“method”的方法,因为没法使用"Class.method"调用该方法,而要说Class有一个实例方法“method”,这意味着必须创建该类的实例对象,通过实例对象调用该方法。
如果要定义类方法,那么在定义方法的时候,必须加类名前缀,如下
class Person def Person.name @name = "xianlinbox" end end
类本身也是对象
在Ruby中Class本身也是一个对象,关于对象的所有规矩都适用于Class.
puts "hello".class #=> String puts String.class #=> Class puts Class.class #=> Class puts Class.instance_methods(false) #=> [:superclass,:allocate,:new] puts Class.instance_variables #=> nil
类的继承体系
puts String.superclass #=> Object puts Class.superclass #=> Module puts Module.superclass #=> Object puts Object.superclass #=> BasicObjec puts BasicObject.superclass #=> nil
- BasicObject是继承体系的根节点。
- 所有类都继承自Object。
- Class是对Module的继承增强,增加了new()和allocate()方法以创建实例。
文章结束给大家分享下程序员的一些笑话语录:
开发时间
项目经理: 如果我再给你一个人,那可以什么时候可以完工?程序员: 3个月吧!项目经理: 那给两个呢?程序员: 1个月吧!
项目经理: 那100呢?程序员: 1年吧!
项目经理: 那10000呢?程序员: 那我将永远无法完成任务.