Ruby class_eval and instance_eval notes

lidashuang發表於2019-02-16

區別:

instance_eval的接受者為物件,為物件建立了一個單鍵方法,class_eval接受者為一個類時,定義一個類的例項方法

當物件是類物件時,該方法成為類方法,因為類也是Class的例項

class_eval

我們有個Game類

class Game
  attr_accessor :name, :owner

  def initialize(name)
    @name = name
  end
end

使用class_eval新增例項方法

Game.class_eval do 
  def hello
    puts "helloworld"
  end
end

我們定義了一個例項方法hello,列印helloworld出來

irb(main):017:0> Game.new("asdf").hello
helloworld
=> nil

也可以用class_eval新增類方法,比如對Game類新增find_by_owner的類方法

程式碼:

Game.class_eval do
  def self.find_by_owner(name)
  end
end

沒有self,則class_eval新增的是例項方法

instance_eval

使用instance_eval設定物件的例項屬性

contra_game = Game.new(`Contra`)

設定contra_game物件的owner例項屬性為Alice

程式碼:

contra_game = Game.new(`Contra`)
contra_game.instance_eval do
   @owner = "Alice"
end

如果對Game類使用instance_eval定義的方法就是Game類的類方法,Game是Class的例項,Game的單鍵方法就是Game類方法

比如這個例子中,定義find_by_owner的類方法

irb(main):018:0> Game.instance_eval do
irb(main):019:1*   def find_by_owner(name)
irb(main):020:2>     puts name
irb(main):021:2>   end
irb(main):022:1> end
=> nil

就可以呼叫定義好的類方法了

irb(main):023:0> Game.find_by_owner("who")
who
=> nil

在物件的上下文中執行一個block

使用instance_evalblock_given? 在Game類的建構函式中實現接受一個可選的block,並呼叫block

class Game
  def initialize(&block)
    instance_eval(&block) if block_given?
  end

  def owner(name=nil)
    if name
      @owner = name
    else
      @owner
    end
  end
end

links

相關文章