包含模块#和扩展模块#和模块#预先进行比较讨论

时间:2013-03-13 14:10:16

标签: ruby module ruby-2.0

任何人都可以帮助我理解以下3种关于他们的方法 功能差异和用途?

  
      
  • 模块#include mod.included(other) other.include(mod)

    之后调用
  •   
  • 模块#extended mod.extended(obj) obj.extend(mod)

    之后调用
  •   
  • 模块#prepended mod.prepended(其他) other.prepend(mod)

    之后调用
  •   

可以用一个例子比较理解上面三个吗?

由于

2 个答案:

答案 0 :(得分:1)

红宝石。您可以将模块包含到另一个类中,该方法将可用于该类的实例。 Extend类似,只是方法作为类方法添加到该类。 More info herehere

Prepend是一项新的2.0功能。 “有时,你想要一个模块中的方法从类中获取方法的优先级。有一些解决方案可以完成这个任务,比如alias_method_chain,但它更像是一个hack而不是任何东西 - 而且不是很安全。” - 也就是说,您有时希望将包含的方法放在类中的方法之前,然后可以使用super来调用类中的原始方法。

这两个链接都有详细的例子,所以一定要检查出来。但是对于包含的内容,预先使用和扩展使用了什么?那么,在你想要包含/扩展/前置的模块上,你可以定义这些函数,当实际的包含/扩展/前置发生时,将调用此方法,并将obj参数设置为你的类正在扩展。例如,当你不想向类中添加方法,但想要向类中添加类变量或实例变量等内容,或者初始化值......无穷无尽的可能性时,这很有用。

示例

假设我有大量的模型,例如评论,帖子,图片等。我不需要复制和粘贴相同的代码来实现一个功能,例如“喜欢”这个东西的功能,我可以改为创建像这样的东西:

module Likable
  def self.included(obj)
    obj.instance_variable_set(:@like_count, 0)
  end
end

class Comment
  include Likable
end

class Picture
  include Likable
end

正如您所看到的,这会自动将名为like_count的新实例变量设置为0.当然,我会添加更多代码,但实质上是在这里,您将一段功能提取到可重用模块中,然后您可以将其放入几个不同的类中。即使您只是为单个类添加功能,有时也会使用此功能,因为这样做的好处是某个功能被提取到一个单独的类中,您可以比与其他功能混合时更容易理解和调整代码

答案 1 :(得分:1)

Module#prepended很好地描述了here以及Ruby 2.0中的另一个新功能

Module#includedModule#extended的工作方式与includeextend类似

这是Rails项目中使用的流行模式:

module Talker

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

  module ClassMethods
    def say(*args)
      args.each do |arg|
        method_name = ("say_" + arg.to_s).to_sym
        send :define_method, method_name do
          puts arg
        end
      end
    end
  end

end

included挂钩include事件(与extended上的extend相同),当模块Talker包含在另一个类中时,它会调用。

通过此功能,我们可以扩展原始类而不是此模式:

class Original
  include Talker
  extend Talker::ClassMethods
  ...
end