代码之家  ›  专栏  ›  技术社区  ›  Peter

鲁比:自我扩展

  •  111
  • Peter  · 技术社区  · 15 年前

    在Ruby中,我了解 extend . 但是,这段代码中发生了什么?具体来说,什么是 延伸 是吗?将实例方法转换为类方法只是一种方便的方法吗?为什么要这样做而不是从一开始就指定类方法?

    module Rake
      include Test::Unit::Assertions
    
      def run_tests # etc.
      end
    
      # what does the next line do?
      extend self
    end
    
    5 回复  |  直到 11 年前
        1
  •  113
  •   cldwalker    15 年前

    将实例方法转换为类方法是一种方便的方法。但你也可以用它作为 more efficient singleton .

        2
  •  29
  •   Matt Gibson    11 年前

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

    puts self
    

    将返回耙 所以,

    extend self
    

    基本上使rake中定义的实例方法对它可用,所以您可以这样做

    Rake.run_tests
    
        3
  •  21
  •   fphilipe    12 年前

    对我来说,想起来总是有帮助的 extend 作为 include 在singleton类中(也称为meta或eigen类)。

    您可能知道在singleton类中定义的方法基本上是类方法:

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

    现在我们知道了, 延伸 包括 模块中的方法位于singleton类中,因此将它们公开为类方法:

    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
  •  13
  •   forforf    12 年前

    为了避免链路损坏,需要 blog post of Chris Wanstrath 由用户83510链接的链接在下面重新发布(经其许可)。 尽管如此,没有什么能比得上原版,所以只要它继续工作,就使用他的链接。


    唱独角戏 2008年11月18日 我就是不明白。比如大卫·鲍伊。或者南半球。但是没有什么能像鲁比·辛格尔顿那样让我的头脑感到迷惑。因为事实上,这是完全不必要的。

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

    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更简洁,代码更易于测试、模拟和存根,而且在需要时转换为适当的类仍然非常简单。

    (版权归Chris Wanstrah所有)

        5
  •  3
  •   Abe Voelker    11 年前

    extend self 包括所有现有的实例方法作为模块方法。这等于说 extend Rake . 阿尔索 Rake 是类的对象 Module .

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

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

    这可用于使用私有方法定义自包含模块。