【问题标题】:Ruby: extend selfRuby:扩展自我
【发布时间】:2009-11-14 03:26:23
【问题描述】:

在Ruby中,我了解extend的基本思想。但是,这段代码发生了什么?具体来说,extend 做了什么?它只是将实例方法变成类方法的一种方便方法吗?为什么要这样做而不是从一开始就指定类方法?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

【问题讨论】:

    标签: ruby


    【解决方案1】:

    将实例方法变成类方法是一种方便的方法。但您也可以将其用作more efficient singleton

    【讨论】:

    • 为什么这种单例更高效?
    • 你的链接已经烂了我的朋友。
    • 用 archive.org 的链接更新了这个答案
    • 这个答案是不充分的,因为它没有解释 如何 有问题的关键字将实例方法变成类方法。它也没有解释什么是“更高效的单例”,或者 extend self 与此有什么关系。
    【解决方案2】:

    在模块中,self 是模块类本身。比如

    puts self
    

    将返回 Rake 所以,

    extend self
    

    基本上让Rake中定义的实例方法对它可用,所以你可以这样做

    Rake.run_tests
    

    【讨论】:

      【解决方案3】:

      对我来说,在单例类(也称为元类或特征类)中将extend 视为include 总是有帮助的。

      你可能知道单例类内部定义的方法基本上都是类方法:

      module A
        class << self
          def x
            puts 'x'
          end
        end
      end
      
      A.x #=> 'x'
      

      现在我们知道,extendinclude 模块中的方法在单例类中,从而将它们公开为类方法:

      module A
        class << self
          include A
      
          def x
            puts 'x'
          end
        end
      
        def y
          puts 'y'
        end
      end
      
      A.x #=> 'x'
      A.y #=> 'y'
      

      【讨论】:

        【解决方案4】:

        为避免链接失效,由user83510链接的blog post of Chris Wanstrath在下面重新发布(经他的许可)。 尽管如此,没有什么能比得上原创,所以只要它继续有效,就使用他的链接。


        → 唱歌单身人士 2008 年 11 月 18 日 有些东西我就是不明白。以大卫鲍伊为例。或者南半球。但没有什么比 Ruby 的 Singleton 更让我难以置信的了。因为真的,完全没有必要。

        这是他们希望您对您的代码执行的操作:

        require 'net/http'
        
        # first you setup your singleton
        class Cheat
          include Singleton
        
          def initialize
            @host = 'http://cheat.errtheblog.com/'
            @http = Net::HTTP.start(URI.parse(@host).host)
          end
        
        
          def sheet(name)
            @http.get("/s/#{name}").body
          end
        end
        
        # then you use it
        Cheat.instance.sheet 'migrations'
        Cheat.instance.sheet 'yahoo_ceo'
        

        但这太疯狂了。与权力战斗。

        require 'net/http'
        
        # here's how we roll
        module Cheat
          extend self
        
          def host
            @host ||= 'http://cheat.errtheblog.com/'
          end
        
          def http
            @http ||= Net::HTTP.start(URI.parse(host).host)
          end
        
          def sheet(name)
            http.get("/s/#{name}").body
          end
        end
        
        # then you use it
        Cheat.sheet 'migrations'
        Cheat.sheet 'singletons'
        

        为什么不呢? API 更简洁,代码更易于测试、模拟和存根,并且在需要时转换为适当的类仍然非常简单。

        ((版权应该十克里斯万斯特拉))

        【讨论】:

        • 另一种避免 linkrot 的方法是使用类似 wayback 机器的东西 -- web.archive.org -- 它保留了整个网络页面的历史记录,我发现它在许多 linkrot 情况下非常有用无论如何。
        【解决方案5】:

        extend self 包含所有现有的实例方法作为模块方法。这相当于说extend RakeRake 也是 Module 类的对象。

        实现等效行为的另一种方法是:

        module Rake
          include Test::Unit::Assertions
        
          def run_tests # etc.
          end
        
        end 
        
        Rake.extend(Rake)
        

        这可以用来定义带有私有方法的自包含模块。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-27
          • 2016-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多