2009-11-14 8 views
103

En Ruby, entiendo la idea básica de extend. Sin embargo, ¿qué está pasando en este segmento de código? Específicamente, ¿qué hace extend? ¿Es solo una forma conveniente de convertir los métodos de instancia en métodos de clase? ¿Por qué lo haría de esta manera en lugar de especificar los métodos de clase desde el principio?Ruby: extiéndete

module Rake 
    include Test::Unit::Assertions 

    def run_tests # etc. 
    end 

    # what does the next line do? 
    extend self 
end 

Respuesta

107

Es un cómodo forma de hacer que los métodos de instancia en los métodos de clase. Pero también puede usarlo como more efficient singleton.

+2

¿Por qué es este tipo de singleton más eficiente? – xuuso

26

En un módulo, uno mismo es la clase de módulo. Así, por ejemplo

puts self 

volverá Rake así,

extend self 

básicamente hace que los métodos de instancia definidas en el rastrillo a su disposición, para que pueda hacer

Rake.run_tests 
14

Para mí siempre ayuda pensar en extend como include dentro de la clase singleton (también conocida como meta o clase propia).

Usted probablemente sabe que los métodos definidos dentro de la clase Singleton son, básicamente, los métodos de clase:

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

A.x #=> 'x' 

Ahora que sabemos que, extend se include los métodos en el módulo dentro de la clase Singleton y por lo tanto exponerlos como de clase métodos:

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

extend self incluye todos los métodos de instancia existentes como los métodos de módulo. Esto es equivalente a decir extend Rake. También Rake es un objeto de la clase Module.

Otra manera de conseguir un comportamiento equivalente será:

module Rake 
    include Test::Unit::Assertions 

    def run_tests # etc. 
    end 

end 

Rake.extend(Rake) 

Esto puede ser usado para definir la auto módulos con métodos privados contenida.

8

Para evitar link rot, el blog post of Chris Wanstrath vinculado por user83510 se vuelve a publicar a continuación (con su permiso). Aún así, nada mejor que un original, así que use su enlace mientras siga funcionando.


→ únicos Cantando 18 de de noviembre de 2008 Hay cosas que simplemente no entiendo. David Bowie, por ejemplo. O el Hemisferio Sur. Pero nada perturba mi mente como el Singleton de Ruby. Porque realmente, es totalmente innecesario.

Esto es lo que quieren que haga con su código:

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' 

Pero eso es una locura. Luchar contra el poder.

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' 
Cualquier

por qué no?La API es más conciso, el código es más fácil de probar, simular y resguardar, y aún es muy fácil convertirlo en una clase adecuada si surge la necesidad.

((copyright ought ten chris wanstrath))

+0

Otra forma de evitar linkrot es usar algo como la máquina de retorno - http://web.archive.org - mantiene un historial de páginas en la web, lo he encontrado bastante útil en muchos casos de linkrot de todos modos . –