簡體   English   中英

instance_eval vs模塊中的class_eval

[英]instance_eval vs class_eval in module

class Foo
    include Module.new { class_eval "def lab; puts 'm' end" }

    def lab
      super 
      puts 'c'
    end
end

Foo.new.lab #=> m c

================================================== ======================

class Foo
    include Module.new { instance_eval "def lab; puts 'm' end" }

    def lab
      super 
      puts 'c'
    end
end

請注意,我將class_eval更改為instance_eval

Foo.new.lab rescue nil#=> no super class method lab
Foo.lab #=> undefined method lab for Foo class

所以似乎包含模塊既沒有定義實例方法也沒有定義類方法。

有什么解釋在這里發生了什么?

此代碼在mac上的ruby 1.8.7上進行了測試。

首先,想到什么include呢。 它使模塊的實例方法被包含在包含類的實例方法中。 即,除了您的工作示例使用匿名模塊這相當於:

module M1
  def lab
    puts 'm'
  end
end

class Foo
    include M1

    def lab
      super 
      puts 'c'
    end
end

接下來,想一想class_eval作用。 它在類或模塊的上下文中評估給定的代碼。 即它就像你重新打開模塊並輸入傳遞給class_eval的代碼class_eval 所以MyModule = Module.new { class_eval "def lab; puts 'm' end" }相當於

module MyModule
  def lab
    puts 'm'
  end
end

希望這能解釋有效的案例。

當你使用instance_eval你正在評估接收對象的上下文中的代碼(在這種情況下是模塊的實例)所以MyMod2 = Module.new { instance_eval "def lab; puts 'm' end" }相當於

module MyMod2
  def MyMod2.lab
    puts 'm'
  end
end

即它創建了一個模塊方法,您可以通過MyMod2.lab調用MyMod2.lab並且這些方法不會被include作為實例方法include


請注意 :這個答案從我寫給前一個問題的答案中借用了一些解釋,這個問題詢問了與 Ruby編程語言書中的一個例子有關的instance_eval與class_eval 您可能會發現答案也很有用。

包括一個模塊只需要實例方法 - 你正在尋找擴展。 幸運的是,為了獲得兩全其美,你可以簡單地做到:

module Something
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def blah
      puts "lol"
    end
  end
end

class Test
  include Something
end 

IRB:

>> Test.blah
lol
=> nil

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM