Ruby:扩展自我

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

 module Rake include Test::Unit::Assertions def run_tests # etc. end # what does the next line do? extend self end 

将实例方法变为类方法是一种方便的方法。 但是你也可以把它作为一个更有效的单例 。

在一个模块中,self是模块类本身。 所以例如

 puts self 

将返回Rake,

 extend self 

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

 Rake.run_tests 

对于我来说,把单元类(也称为元类或特征类) include在内,总是有帮助的。

你可能知道在单例类中定义的方法基本上是类方法:

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

现在我们知道了, extend将在singleton类中的模块中include这些方法,从而将它们公开为类方法:

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

为了避免链接腐烂,由user83510链接的Chris Wanstrath的博客文章在他的许可下转贴。 尽pipe如此,没有什么比击败原创,所以只要继续工作,就使用他的链接。


→singin'singletons 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更简洁,代码更容易testing,模拟和存根,如果需要的话,转换成适当的类仍然很简单。

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

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

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

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

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