繁体   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