Ruby class_eval and instance_eval notes

更新于 2014-07-18  约 4 分钟

区别:

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

阅读 1.8k更新于 2014-07-18

推荐阅读
lidashuang's note
用户专栏

Happy Hacking

11 人关注
63 篇文章
专栏主页
目录