Ruby:扩展自我

时间:2009-11-14 03:26:24

标签: ruby

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

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

5 个答案:

答案 0 :(得分:114)

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

答案 1 :(得分:29)

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

puts self

将返回Rake 所以,

extend self

基本上使得Rake中定义的实例方法可用,所以你可以做到

Rake.run_tests

答案 2 :(得分:21)

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

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

module A
  class << self
    def x
      puts 'x'
    end
  end
end

A.x #=> 'x'

既然我们知道,extend将会include单例类中模块中的方法,从而将它们作为类方法公开:

module A
  class << self
    include A

    def x
      puts 'x'
    end
  end

  def y
    puts 'y'
  end
end

A.x #=> 'x'
A.y #=> 'y'

答案 3 :(得分:14)

为避免链接损坏,用户83510链接的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更简洁,代码更容易测试,模拟和存根,并且在需要时转换为适当的类仍然很简单。

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

答案 4 :(得分:3)

extend self包括所有现有的实例方法作为模块方法。这相当于说extend Rake。此外,Rake是类Module的对象。

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

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

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