[转]Ruby之类的真相

打开类和猴子补丁 
在Ruby中,类定义的方法和其他的语句没有任何区别,都是一行一行的执行下去的。如下例子: 

Ruby代码  收藏代码
  1. class Example  
  2.   def method_1  
  3.     puts "method 1"  
  4.   end  
  5. end  
  6. class Example  
  7.   def method_2  
  8.     puts "method 2"  
  9.   end  
  10. end  


本例中,当第一次定义Class Example的时候,还没有一个叫做Example的Class存在,因此,Ruby开始定义这个类,当后面在定义这个类时,Ruby会发现该类已存在,并返回这个类,而不是定义一个新类。 

因为这个特性,因此,Ruby天生具有打开一个已经存在的类,并动态修改其内容的能力,即使其是标准类库的类也不例外。比方说,可以给SDK的String类添加一个去除String中的标点符号和特殊字符的方法:to_alphanumeric

Ruby代码  收藏代码
  1. class String  
  2.   def to_alphanumeric  
  3.     gsub /[^\w\s]/, ''  
  4.   end  
  5. end  
  6. “H&&^^ello”.to_alphanumeric  #==>Hello  


,然后,所有的String对象都具备“to_alphanumeric”的能力了,这种技术一般简称为打开类技术。 

上面描述的打开类技术其实是隐含了一定的风险的,尤其是在大型系统中使用打开类技术扩展标准类库时,因为,很多开发人员都在扩展类,当多个扩展方法的名字一样时, 后定义的总会覆盖掉前面,从而导致整个系统的崩溃,业界把这种鲁莽的修改类的方式简称为猴子补丁(Monkey Patch)。因此在使用打开类技术时,一定要慎之又慎。 

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

Ruby代码  收藏代码
  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”,这意味着必须创建该类的实例对象,通过实例对象调用该方法。 

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

Ruby代码  收藏代码
  1. class Person  
  2.   def Person.name  
  3.     @name = "xianlinbox"  
  4.   end  
  5. end  



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

Ruby代码  收藏代码
  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  



类的继承体系 

Ruby代码  收藏代码
  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()方法以创建实例。
posted @ 2016-11-28 16:19  超级大熊  阅读(118)  评论(0编辑  收藏  举报