欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Ruby中的instance_eval方法及其與class_eval的對(duì)比

 更新時(shí)間:2016年05月19日 16:12:23   作者:kevinhua  
Ruby的eval族方法將字符串作為代碼來(lái)執(zhí)行,instance_eval方法便是其中之一,下面就來(lái)詳解Ruby中的instance_eval方法及其與class_eval的對(duì)比

instance_eval方法

這個(gè)BasicObject#instance_eval有點(diǎn)類(lèi)似JS中的bind方法,不同的時(shí),bind是將this傳入到對(duì)象中,而instance_eval則是將代碼塊(上下文探針Context Probe)傳入到指定的對(duì)象中,一個(gè)是傳對(duì)象,一個(gè)是傳執(zhí)行體。通過(guò)這種方式就可以在instance_eval中的代碼塊里訪問(wèn)到調(diào)用者對(duì)象中的變量。

示例代碼

class MyClass
  def initialize
    @v = 1
  end
end
obj = MyClass.new

obj.instance_eval do
  self  #=> #<MyClass:0x33333 @v=1>
  @v   #=> 1 
end

v = 2
obj.instance_eval { @v = v }
obj.instance_eval { @v }  # => 2

此外,instance_eval方法還有一個(gè)雙胞胎兄弟:instance_exec方法。相比前者后者更加靈活,允許對(duì)代碼塊傳入?yún)?shù)。

示例代碼

class C
  def initialize
    @x = 1
  end
end
class D
  def twisted_method
    @y = 2
    #C.new.instance_eval { “@x: #{@x}, @y>: #{y}” }
    C.new.instance_exec(@y) { |y| “@x: #{@x}, @y: #{y}” }
  end
end
#D.new.twisted_method  # => “@x: 1, @y: ”
D.new.twisted_method  # => “@x: 1, @y: 2”

因?yàn)檎{(diào)用instance_eval后,將調(diào)用者作為了當(dāng)前的self,所以作用域更換到了class C中,之前的作用域就不生效了。這時(shí)如果還想訪問(wèn)到之前@y變量,就需要通過(guò)參數(shù)打包上@y一起隨instance_eval轉(zhuǎn)義,但因?yàn)閕nstance_eval不能攜帶參數(shù),所以使用其同胞兄弟instance_exec方法。


instance_eval 與 class_eval 的區(qū)別
###instance_eval
首先從名字可以得到的信息是,instance_eval的調(diào)用者receiver必須是一個(gè)實(shí)例instance,而在instance_eval block的內(nèi)部,self即為receiver實(shí)例本身。

obj_instance.instance_eval do
 self # => obj_instance
 # current class => obj_instance's singleton class
end
<!--more-->

根據(jù)這個(gè)定義,如果在一個(gè)實(shí)例上調(diào)用了instance_eval,就可以在其中定義該實(shí)例的單態(tài)函數(shù) singleton_method

class A
end

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

a.method1
#=> this is a singleton method of instance a

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

同樣,因?yàn)轭?lèi)class本身也是Class類(lèi)的一個(gè)實(shí)例,instance_eval也可以用在類(lèi)上,這個(gè)時(shí)候就可以在其中定義該類(lèi)的singleton_method,即為該類(lèi)的類(lèi)函數(shù)。

換句話說(shuō),可以用instance_eval來(lái)定義類(lèi)函數(shù)class method,這比較容易混淆,需要搞清楚。

class A
end

A.instance_eval do
 self # => A
 # current class => A's singleton class
 def method1
  puts 'this is a singleton method of class A'
 end
end

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

###class_eval

再來(lái)看class_eval,首先從名字可以得到的信息是,class_eval的調(diào)用者receiver必須是一個(gè)類(lèi),而在class_eval block的內(nèi)部,self即為receiver類(lèi)本身。

class A
end

A.class_eval do
 self # => A
 # current class => A
end

根據(jù)這個(gè)定義,如果在一個(gè)類(lèi)上調(diào)用了class_eval,就可以在其中定義該類(lèi)的實(shí)例函數(shù) instance_method

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

換句話說(shuō),可以用class_eval來(lái)定義實(shí)例函數(shù)instance method,這也比較容易混淆,需要搞清楚。

相關(guān)文章

最新評(píng)論