2015-02-08 50 views
1

似乎我很困惑這兩種方法雖然我一直在使用它們一段時間,但我不明白爲什麼方法乘客未被添加到下面的代碼中的對象:Ruby元編程:instance_eval和class_eval

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感到困惑!我期待class_eval總線將意味着評估在總線類別class塊。
+0

乘客方法正常:'Bus.passengers#=> 12'。將'Bus.instance_eval'更改爲'Bus.class_eval'以使乘客成爲實例方法。 – 2015-02-08 06:47:41

+0

你也可以使用'Bus.send(:define_method,:passengers){12}'。 – 2015-02-08 07:00:14

+0

除了'如何工作',這絕對是非常奇怪的行爲。 – Renra 2015-02-08 07:29:47

回答

4

你可以參考this階級,真棒文章instance_eval,爲什麼乘客沒有被添加到對象。

TL; DR:

Bus.class_eval will創建實例方法和Bus.instance_eval將創建類的方法。

現在,關於目的地(其可以在例如被調用)的行爲.....要麼class_evalinstance_eval不受通常行爲內使用時定義方法。爲什麼?。

因爲文檔中是這樣說的。根據文檔:

define method - 定義接收器中的實例方法。

因此,如果您使用define_methodclass_evalinstance_eval它總是創建一個實例方法也沒關係。

Source for reference.

希望這有助於:-)。