Ruby: extender uno mismo


En Ruby, entiendo la idea básica de extend. Sin embargo, ¿qué está sucediendo 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 métodos de clase desde el principio?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end
 109
Author: Peter, 2009-11-14

5 answers

Es una forma conveniente de convertir los métodos de instancia en métodos de clase. Pero también se puede utilizar como un singleton más eficiente.

 113
Author: cldwalker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-14 03:57:49

En un módulo, self es la clase de módulo en sí. Así, por ejemplo

puts self

Devolverá el rastrillo así,

extend self

Básicamente hace que los métodos de instancia definidos en Rake estén disponibles para él, por lo que puede hacer

Rake.run_tests
 28
Author: ennuikiller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-01 21:46:51

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

Probablemente sepa que los métodos definidos dentro de la clase singleton son básicamente métodos de clase:

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

A.x #=> 'x'

Ahora que sabemos que, extend include los métodos en el módulo dentro de la clase singleton y así exponerlos como métodos de clase:

module A
  class << self
    include A

    def x
      puts 'x'
    end
  end

  def y
    puts 'y'
  end
end

A.x #=> 'x'
A.y #=> 'y'
 18
Author: fphilipe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-23 07:10:31

Para evitar la putrefacción de enlaces, la entrada del blog de Chris Wanstrath enlazada por user83510 se vuelve a publicar a continuación (con su permiso). Aún así, nada supera a un original, así que use su enlace mientras siga funcionando.


→ singin ' singletons 18 de noviembre de 2008 Hay cosas que no entiendo. David Bowie, por ejemplo. O el Hemisferio Sur. Pero nada me sorprende como el Singleton de Ruby. Porque en realidad, es totalmente innecesario.

Esto es lo que quieren usted tiene que ver 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. Lucha 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'

Cualquiera ¿por qué no? La API es más concisa, el código es más fácil de probar, simular y stub, y todavía es muy simple convertir en una clase adecuada si surge la necesidad.

((copyright ought ten chris wanstrath))

 8
Author: forforf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-22 22:29:50

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

Otra forma de lograr un comportamiento equivalente será:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

Esto se puede usar para definir módulos autónomos con métodos privados.

 3
Author: Sulabh Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-14 19:56:37