他们主要特点

  • class 《 object : 给当前对象object(可能是类本身,或者实例对象)添加 singleton_method
  • object.instance_eval : 给当前对象object(可能是类本身,或者实例对象)添加 singleton_method 与class 《 object相似
  • Object.class_eval : 相当于(但实事不是)打开当前Object(只能是类) 给他添加 实例方法,具体原理看下面分析

他们具体的区别

class 《 object

object 可能是类本身,或者实例对象

  • object 是一个实例对象,则添加的方法只对该实例对象生效
  a = Array.new
  class  a
     def size
        puts super
        "Hello,World"
     end
  end
  puts a.size =======>
  0
  "Hello,World"
  # 另一个实例对象无效
  b = Array.new
  puts b.size =========>
  0
  
  • object 是一个类,则可以理解为给该类添加了一个类方法
  1.9.3-p374 :025 > class A
  1.9.3-p374 :026?>   end
   => nil
  1.9.3-p374 :027 > class  A
  1.9.3-p374 :028?>   def f
  1.9.3-p374 :029?>     p "2"
  1.9.3-p374 :030?>     end
  1.9.3-p374 :031?>   end
   => nil
  1.9.3-p374 :032 > A.f
  "2"
   => "2"
  1.9.3-p374 :033 > A.new.f
  NoMethodError: undefined method `f' for #<A:0x00000002db3790>
  

object.instance_eval

首先从名字可以得到的信息是,instance_eval的调用者receiver必须是一个实例instance,而在instance_eval block的内部,self即为receiver实例本身 同样,因为类class本身也是Class类的一个实例,instance_eval也可以用在类上,这个时候就可以在其中定义该类的singleton_method,即为该类的类方法 所以object 可能是类本身,或者实例对象

  • object 是一个实例对象,则添加的方法只对该实例对象生效
  1.9.3-p374 :044 > class A
  1.9.3-p374 :045?>   end
   => nil
  1.9.3-p374 :046 >  a = A.new
   => #<A:0x00000002defdf8>
  1.9.3-p374 :047 > a.instance_eval do
  1.9.3-p374 :048 >     def c
  1.9.3-p374 :049?>     p "2"
  1.9.3-p374 :050?>     end
  1.9.3-p374 :051?>   end
   => nil
  1.9.3-p374 :052 > A.c
  NoMethodError: undefined method `c' for #<A:0x00000002db3790>
  1.9.3-p374 :054 > d = A.new
   => #<A:0x00000002e0eb40>
 1.9.3-p374 :055 > d.c
  NoMethodError: undefined method `c' for #<A:0x00000002e0eb40>
  1.9.3-p374 :053 > a.c
  "2"
   => "2"

  
  • object 是一个类,则可以理解为给该类添加了一个类方法

  1.9.3-p374 :035 > class A
  1.9.3-p374 :036?>   end
   => nil
  1.9.3-p374 :037 > A.instance_eval do
  1.9.3-p374 :038 >     def u
  1.9.3-p374 :039?>      p "2"
  1.9.3-p374 :040?>     end
  1.9.3-p374 :041?>   end
   => nil
  1.9.3-p374 :042 > A.u
  "2"
   => "2"
  1.9.3-p374 :043 > A.new.u
  NoMethodError: undefined method `u' for #<A:0x00000002de15a0>

所以 假如我像下面这样定义:

  Array.instance_eval do
    def hint
     "hello"
    end
  end

本质上相当于这样的代码:

  class Array
    def self.hint
      "hello"
    end
  end

  #同时,也可以是这样
  class Array
  end

  def Array.hint
     "hell0"
  end

  #当然,也可以是这样
  class Array
    class  self
      def hint
        "hello"
      end
    end
  end

###class_eval

class_module是从Module中得到的,所以class_module的接受者必须是个类 换句话说class_eval的调用者receiver必须是一个类,而在class_eval block的内部,self即为receiver类本身。 我们知道在混合编程(mix)中,include 某个Module时,该Module的所有实例方法只能由子类的实例所调用(相当于多了继承于Module),故class_eval定义之后,只能是Array的所有的实例调用,Array自己调用会出错(肯定的,假如Array自己调用不出错的话,这个方法就是静态方法了) 所以 Object.class_eval 实质就是给当前这个类添加了 实例方法

class A
end

a = A.new
a.method1
#=> NoMethodError: undefined method `method1' for #<A:0x10043ff70>

A.class_eval do
  self  # => A
  # current class => A
  def method1
    puts 'this is a instance method of class A'
  end
end

a.method1
#=> this is a instance method of class A

A.method1
#=> NoMethodError: undefined method `method1' for A:Class

总结

  • class 《 object : 其实就是操作的object eigenclass
  • object.instance_eval : 其实就是操作的object eigenclass
  • Object.class_eval : 其实修改的是Object的类体

声明:未经申明,所有文章,皆为原创,版权均属@Byronlee所有。若需转载,请在文章页面明显位置给出原文连接,否则保留追究法律责任的权利!



blog comments powered by Disqus