`

实例方法和类方法(三)

    博客分类:
  • Ruby
阅读更多

这一次,让我们搞一些破坏性实验,来验证上两次的内容

第一个破坏性实验,module里定义self.xxx方法

ruby 代码
  1. irb(main):001:0> module M   
  2. irb(main):002:1> def self.method_with_self   
  3. irb(main):003:2> end  
  4. irb(main):004:1> end  
  5. => nil  
  6. irb(main):005:0> class A   
  7. irb(main):006:1> include M   
  8. irb(main):007:1> end  
  9. => A   
  10. irb(main):008:0> A.methods - Class.methods   
  11. => [] #空的,你能想到为什么么?  

让我仔细看看,我们定义的方法呢?
ruby 代码
  1. irb(main):009:0> M.singleton_methods   
  2. => ["method_with_self"]  #原来跑到M的单例类里面去了,别忘了,module也是Class  
好了,上面是include,那么,extend会发生什么情况呢?
ruby 代码
  1. irb(main):010:0> class B   
  2. irb(main):011:1> end  
  3. => nil  
  4. irb(main):012:0> B.extend M   
  5. => B   
  6. irb(main):013:0> B.ancestors   
  7. => [B, Object, Kernel]  

ok,再来让我们看看B的单例类此时发生了什么变化
ruby 代码
  1. irb(main):014:0> singleton_class_of_b = class<<B;self;end  
  2. => #<Class:B>   
  3. irb(main):015:0> singleton_class_of_b.ancestors   
  4. => [M, ClassModuleObject, Kernel]  #正如我们预料的,M变成了B单例类的直接父类  


正如预料的,M变成了B单例类的直接父类,M中定义的实例方法,变成了B的类方法(因为M中的实例方法被B的单件类继承,变成了单件类的实例方法,也就是B的类方法),M中定义的以self开头的类方法呢?当然仍然在M的单件类里面啦,它是不会随着M插入点的变化而变化的。

第二个破坏性实验,单件类中的self.xxx方法?

ruby 代码
  1. irb(main):001:0> class A   
  2. irb(main):002:1> end  
  3. => nil  
  4. irb(main):003:0> class<<A   
  5. irb(main):004:1> def self.method_defined_in_singleton_class_of_a   
  6. irb(main):005:2> end  
  7. irb(main):006:1> end  
  8. => nil  
  9. irb(main):007:0> A.singleton_methods   
  10. => []  #看来定义的singleton方法并不属于A   
  11. irb(main):008:0> singleton_class_of_a = class<<A;self;end  
  12. => #<Class:A> #A的单件类   
  13. irb(main):009:0> singleton_class_of_a.singleton_methods   
  14. => ["method_defined_in_singleton_class_of_a""new""nesting"]   
  15. #原来变成了A的单件类的singleton方法  


看了上面代码后想想其实很自然,我们之前说过“所有的类方法都是放在这个类对象的单例类中”,所以,我们新建的这个方法method_defined_in_singleton_class_of_a实际上是放到了A的singleton class <A>的singleton class<A<A>>中的。

第三个破坏性实验,找不到直接父类M?

ruby 代码
  1. irb(main):001:0> module M   
  2. irb(main):002:1> def self.class_method_defined_in_m   
  3. irb(main):003:2> puts "singleton method in m"  
  4. irb(main):004:2> end  
  5. irb(main):005:1> end  
  6. => nil  
  7. irb(main):006:0> class A   
  8. irb(main):007:1> include M   
  9. irb(main):008:1> end  
  10. => A   
  11. irb(main):009:0> A.ancestors   
  12. => [A, M, Object, Kernel]   
  13. irb(main):010:0> A.superclass   
  14. => Object  
上面irb结果可以看到,从继承树上来看A的直接父类是M,但是当我们调用A.superclass的时候却跳过了这个M,为什么呢?正如之前所说,我们在继承树上看到的M,其实只是M的一个代理,他的作用仅仅是用来做方法查找,让A变成一个代理类的子类,是没有意义的,所以,虽然实际上A确实称为了代理类的子类,但是从逻辑上讲,它的继承关系并没有被改变,它从逻辑上仍然是Object的直接子类
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics