zoukankan      html  css  js  c++  java
  • [转] ruby之对象体系

    转自:http://blog.csdn.net/feigeswjtu/article/details/51040006

    标题叫“对象”呢?不是还有类、Module等这些呢,为什么不介绍呢?不急,听我慢慢道来。

    对象里有什么?

    我们讲讲普通对象,也就是通过类new出来的对象有什么?

    先举个例子:

    [ruby] view plain copy
     
    1. class TestClass  
    2.     def test_method  
    3.       @v  
    4.     end  
    5. end  
    6. obj = TestClass.new  #<TestClass:0x0000000136ca08>  
    7. obj.class #TestClass  

    obj里有什么呢?

    实例变量

    [javascript] view plain copy
     
    1. obj.instance_variables #[]  
    2. obj.test_method #nil  
    3. obj.instance_variables #[:@v]  
    通过instance_variables可以得到对象的所有实例方法,这里提一下,为什么第一次调用的时候没有@v这个实例变量呢?这也是ruby很灵活的一个地方,那就是任何一个方法或者一个实例变量,甚至是类变量都可以在运行中生成,以我们的例子来说,如果不调用test_method方法的话,@v变量永远不存存在obj对象里。

    方法

    那么方法test_method是存在于类里,还是对象里呢?
    我们看看:
    [ruby] view plain copy
     
    1. 2.1.1 :018 > obj.methods  
    2.  => [:test_method, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]  
     
    [ruby] view plain copy
     
    1. 2.1.1 :019 > TestClass.methods  
    2.  => [:allocate, :new, :superclass, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :singleton_class?, :include, :prepend, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]  

    [ruby] view plain copy
     
    1. 2.1.1 :020 > TestClass.instance_methods  
    2.  => [:test_method, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]   

    从上面的结果可以看出,obj的方法也是TestClass的实例方法,可以说obj有一个test_mothod方法,但是不能说TestClass有test_method方法,这样就可以说test_method方法就是属于obj吗,NONO,它还是属于TestClass,因为obj除了有自身的实例变量之外,还有一个本身类的引用,就是说它的方法实际上找到类中定义的实例方法才能调用的,本身是不存在这些方法的。
     
    到这,我们可以简单的花一个图:
     
     到这里,我们总结一下,一个对象的实例变量存在于对象本身,但是一个对象的方法却存在于对象对应的类里,这就是同一个类的对象共享相同的方法,但是不会共享实例变量,我们再用一个例子描述一下,我们先创建一个类,并且对这个类实例化一个对象,然后在打开这个类,新增一个方法并且在这个方法里生成一个实例变量,最后再用这个类实例化一个对象,看看前后实例化的对象有什么差别。
     


    如图,obj1在未打开类之前是没有test_methods这个方法的,打开类,重新给类定义一个方法,即使打开类是在obj1实例化之后,obj1也是会有test_method这个方法的,我们以此证明了上面的结论。

    什么是类

    在ruby里,我们要永远记住一句:类也是对象。我们知道,在ruby进程里,每一个对象都有一个对象id,可以通过obj.object_id拿到,一个类也是有object_id的:

    [ruby] view plain copy
     
    1. 1.9.3-p551 :007 > String.object_id  
    2.  => 10636640  

    那么类是个对象,那么类的类是什么呢?

    [ruby] view plain copy
     
    1. 1.9.3-p551 :008 > String.class  
    2.  => Class   
    3. 1.9.3-p551 :009 > Class.class  
    4.  => Class  

    类的类是Class,Class的类也是Class。

    既然说,普通类的类的类是Class,而Class也是一个类,抱歉,有点绕,那么能不能通过Class去创建一个新的类的,答案是能:

    [ruby] view plain copy
     
    1. DemoClass = Class.new do  
    2.   def put_class_name  
    3.     puts self.class  
    4.   end  
    5. end  
    [ruby] view plain copy
     
    1. irb(main):006:0> d = DemoClass.new  
    2. => #<DemoClass:0x007f490dba4ae8>  
    3. irb(main):007:0> d.put_class_name  
    4. DemoClass  

    很神奇吧。

    什么是Module

    Module是Class的父类,Class和Module的差别是Class是一个增强的Module,它比Module多了一个new,allocate方法,除了这一个区别,当然这个区别特别重要,Class和Module基本是一样的。在用途上,Class可以include一个Module之后拥有module里定义的方法。

    注意:这里只能拥有Module里的实例方法,类方法是无法使用的:

    [ruby] view plain copy
     
    1. module DemoModule  
    2.   class << self  
    3.     def getClassName  
    4.       self.to_s  
    5.     end                          
    6.   end  
    7.    
    8.   def initialize(*args)  
    9.     @initialized = true  
    10.   end  
    11.     
    12.   def initialized?  
    13.     @initialized || false  
    14.   end  
    15. end  
    16.   
    17. class DemoClass  
    18.   include DemoModule  
    19. end  
    20.   
    21. puts DemoModule.getClassName #DemoModule  
    22. puts DemoClass.new.initialized? #true  
    23. puts DemoClass.getClassName # undefined method `getClassName' for DemoClass:Class (NoMethodError)  


    那么Class的父类是Module,那么Module的父类是什么呢?我们看看:

    [ruby] view plain copy
     
    1. 1.9.3-p551 :009 > 'aa'.class  
    2.  => String   
    3. 1.9.3-p551 :010 > String.class  
    4.  => Class   
    5. 1.9.3-p551 :011 > String.superclass  
    6.  => Object   
    7. 1.9.3-p551 :012 > Module.class  
    8.  => Class   
    9. 1.9.3-p551 :013 > Module.superclass  
    10.  => Object   
    11. 1.9.3-p551 :014 > Object.class  
    12.  => Class   
    13. 1.9.3-p551 :015 > Object.superclass  
    14.  => BasicObject   
    15. 1.9.3-p551 :016 > BasicObject.class  
    16.  => Class   
    17. 1.9.3-p551 :017 > BasicObject.superclass  
    18.  => nil   

    我们从实例对象到Class再到Module一直往上走,最终会走到BasicObject,实际上BasicObject就是Ruby对象体系里的跟节点。

    说到这,我们简单的介绍一下Class和Module的区别。

    我们情不自禁的要问,为什么类和模块之间那么相似,还要存在不同的两个概念呢,不是多此一举吗?不是这样的,同时存在模块和类的主要原因是为了让代码更加清晰。

    我总结了一下,主要原因有三点:

    1. 如果有一个模块是公用的,定义出来本身是为了在别处用,而本身并没有什么业务上的作用,一般是让别的地方include或者是为了当初命名空间使用,那么这个时候就要作为模块。

    2. 当希望它被实例化或者为了继承扩展时,就应该使用类。

    所以使用的时候应该根据自己目的和使用方式来选择使用。

    对象体系关系图

    到此,我们可以画出Ruby对象体系里的关系图:

    到这我们可以对ruby中的对象做个总结:

    什么是对象?ruby中的对象是无非就是一组实例变量外加一个指向它的类的一个引用,通过这个引用可以拿到实例方法,因为对象的方法不是存在于对象其本身,而是存在于对象所属于的类里。

    什么是类?类就是一个对象外加一组实例方法和一个对其超类的引用。Class是Module的子类,所以一个Class就是一个Module。只是比模块多了一些方法。和普通的对象一样,类必须通过引用进行访问,这个引用就是类名。

  • 相关阅读:
    Vue.js+express建站
    单页应用(SPA)简介
    Z形记之CentOS7
    Z形记之比较两个目录下文件异同
    Z形记之Linux的那些事:安装Nginx
    SQL之修改字段类型
    Scrapy系列之爬取豆瓣电影
    Scrapy和MongoDB的应用---爬取
    BigDecimal类的常用算法
    回到顶部功能
  • 原文地址:https://www.cnblogs.com/linganxiong/p/6109604.html
Copyright © 2011-2022 走看看