詳解Ruby中的instance_eval方法及其與class_eval的對比_ruby專題

來源:互聯網
上載者:User

instance_eval方法

這個BasicObject#instance_eval有點類似JS中的bind方法,不同的時,bind是將this傳入到對象中,而instance_eval則是將代碼塊(上下文探針Context Probe)傳入到指定的對象中,一個是傳對象,一個是傳執行體。通過這種方式就可以在instance_eval中的代碼塊裡訪問到調用者對象中的變數。

範例程式碼

class MyClass  def initialize    @v = 1  endendobj = MyClass.newobj.instance_eval do  self  #=> #<MyClass:0x33333 @v=1>  @v   #=> 1 endv = 2obj.instance_eval { @v = v }obj.instance_eval { @v }  # => 2

此外,instance_eval方法還有一個雙胞胎兄弟:instance_exec方法。相比前者後者更加靈活,允許對代碼塊傳入參數。

範例程式碼

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

因為調用instance_eval後,將調用者作為了當前的self,所以範圍更換到了class C中,之前的範圍就不生效了。這時如果還想訪問到之前@y變數,就需要通過參數打包上@y一起隨instance_eval轉義,但因為instance_eval不能攜帶參數,所以使用其同胞兄弟instance_exec方法。


instance_eval 與 class_eval 的區別
###instance_eval
首先從名字可以得到的資訊是,instance_eval的調用者receiver必須是一個執行個體instance,而在instance_eval block的內部,self即為receiver執行個體本身。

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

根據這個定義,如果在一個執行個體上調用了instance_eval,就可以在其中定義該執行個體的單態函數 singleton_method

class Aenda = A.newa.instance_eval do self # => a # current class => a's singleton class def method1  puts 'this is a singleton method of instance a' endenda.method1#=> this is a singleton method of instance ab = A.newb.method1#=>NoMethodError: undefined method `method1' for #<A:0x10043ff70>

同樣,因為類class本身也是Class類的一個執行個體,instance_eval也可以用在類上,這個時候就可以在其中定義該類的singleton_method,即為該類的類函數。

換句話說,可以用instance_eval來定義類函數class method,這比較容易混淆,需要搞清楚。

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

###class_eval

再來看class_eval,首先從名字可以得到的資訊是,class_eval的調用者receiver必須是一個類,而在class_eval block的內部,self即為receiver類本身。

class AendA.class_eval do self # => A # current class => Aend

根據這個定義,如果在一個類上調用了class_eval,就可以在其中定義該類的執行個體函數 instance_method

class Aenda = A.newa.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' endenda.method1#=> this is a instance method of class A

換句話說,可以用class_eval來定義執行個體函數instance method,這也比較容易混淆,需要搞清楚。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.