Ruby元编程:instance_eval和class_eval

时间:2015-02-08 06:43:04

标签: ruby metaprogramming

似乎我在两种方法之间感到困惑,虽然我已经使用了一段时间,我无法理解为什么方法 passenger 没有被添加到以下代码中的对象:< / p>

class Bus
  def number_of_seats
    42
  end
end

Bus.class_eval do
  define_method :number_of_windows do
    number_of_seats
  end

  def fuel_type
    :diesel
  end
end

Bus.instance_eval do
  define_method :destination do
    'Paris'
  end

  def passengers
    12
  end
end

bus = Bus.new
bus.number_of_windows # => 42
bus.fuel_type # => :diesel
bus.destination # => "Paris"
bus.passengers # => undefined method `passengers' (NoMethodError)

备注

  • 首先尝试instance_eval,随机使用class_eval,然后它似乎也有效!
  • 我对instance_eval块的理解:块中的代码运行时self设置为调用instance_eval的对象。
  • 我对class_eval块的理解:通过打开调用它的对象的类来评估块中的代码。因此,我对上述案例中的class_eval感到困惑!我希望 Bus 上的class_eval意味着评估 Bus Class class中的块。

2 个答案:

答案 0 :(得分:4)

您可以在课堂上提及this精彩文章,并在instance_eval上提及未将旅客添加到对象中的原因。

TL; DR:

Bus.class_eval will创建实例方法,Bus.instance_eval将创建类方法。

现在,关于目的地的行为(可以在实例上调用)..... class_evalinstance_eval内使用时定义方法对通常的行为免疫。为什么呢?

因为文档说明了这一点。根据文件:

  

define method - 在接收器中定义实例方法。

因此,如果您在define_methodclass_eval内使用instance_eval,则始终会创建实例方法。

Source for reference.

希望这有助于: - )。

答案 1 :(得分:0)

基本上,在使用instance_eval时,您无法对类对象执行def。这是您使用instance_evalclass_eval的一般方式。 http://web.stanford.edu/~ouster/cgi-bin/cs142-winter15/classEval.php