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 Rake
。 Rake
也是类Module
一个对象。
另一种实现等同行为的方法是:
module Rake include Test::Unit::Assertions def run_tests # etc. end end Rake.extend(Rake)
这可以用来用私有方法定义自包含的模块。