Ruby:扩展自我


113

在Ruby中,我了解的基本概念extend。但是,这段代码中发生了什么?具体来说,该怎么extend办?这仅仅是将实例方法转换为类方法的便捷方法吗?您为什么要这样做而不是从一开始就指定类方法?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

Answers:


115

这是将实例方法转换为类方法的便捷方法。但是您也可以将其用作更有效的单例


2
为什么这种单例更有效率?
xuuso

5
您的链接烂了我的朋友。
Ulysse BN

1
使用指向archive.org的链接更新了此答案
Mike Szyndel

1
这个答案是不够的,因为它没有解释所讨论的关键字如何将实例方法变成类方法。它也没有解释什么是“更有效的单身人士”,或者extend self与之有什么关系。
jayqui

29

在模块中,self是模块类本身。所以举个例子

puts self

将返回Rake,

extend self

基本上使Rake中定义的实例方法可用,因此您可以

Rake.run_tests

23

对我而言,将其extend视为include单例类(也称为元或本征类)内部总是很有帮助的。

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

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'

15

为了避免链接腐烂,由user83510链接的Chris Wanstrath博客文章重新张贴在下面(未经他的许可)。不过,没有什么能比原始作品更好,因此只要可以继续使用,就使用他的链接。


→singin'singletons 2008年11月18日,有些东西我只是听不懂。例如,大卫·鲍伊(David Bowie)。或南半球。但是,没有什么比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是使用类似自由之路机- web.archive.org -它使跨网页的历史记录,我发现它在linkrot的许多情况下,反正非常有用。
凯姆·梅森

3

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

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

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.