延伸自我

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

module Rake
include Test::Unit::Assertions


def run_tests # etc.
end


# what does the next line do?
extend self
end
35243 次浏览

在模块中,self 是模块类本身

puts self

会把雷克送回来 所以,

extend self

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

Rake.run_tests

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

For me it always helps to think of extend as include inside the singleton class (also known as meta or eigen class).

您可能知道,单例类中定义的方法基本上都是类方法:

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'

extend self includes all the existing instance methods as module methods. This is equivalent to saying extend Rake. Also Rake is an object of class Module.

达到同等行为的另一种方法是:

module Rake
include Test::Unit::Assertions


def run_tests # etc.
end


end


Rake.extend(Rake)

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

为了避免链接腐烂,用户83510链接的 Chris Wanstrath 的博客文章在下面重新发布(经过他的许可)。 尽管如此,没有什么能打败原创者,所以只要他的链接继续工作,就要使用它。


→独唱 18 November 2008 有些事我就是不明白。比如 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'

But that’s crazy. Fight the power.

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 更简洁,代码更容易测试、模拟和存根,而且如果需要的话,转换成合适的类仍然非常简单。

((版权所有: 10 Chris Wanstrath))