Ruby: estendi se stesso


113

In Ruby, capisco l'idea di base di extend. Tuttavia, cosa sta succedendo in questo segmento di codice? Nello specifico, cosa fa extend? È solo un modo conveniente per trasformare i metodi di istanza in metodi di classe? Perché dovresti farlo in questo modo invece di specificare i metodi di classe dall'inizio?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

Risposte:


115

È un modo conveniente per trasformare i metodi di istanza in metodi di classe. Ma puoi anche usarlo come singleton più efficiente .


2
Perché quel tipo di singleton è più efficiente?
xuuso

5
Il tuo collegamento è marcio amico mio.
Ulysse BN

1
Aggiornata questa risposta con un collegamento a archive.org
Mike Szyndel,

1
Questa risposta è inadeguata perché non spiega come la parola chiave in questione trasforma i metodi di istanza in metodi di classe. Inoltre non spiega cosa sia un "singleton più efficiente" o cosa extend selfabbia a che fare con questo.
jayqui

29

In un modulo, self è la classe del modulo stessa. Quindi per esempio

puts self

restituirà Rake così,

extend self

fondamentalmente rende disponibili i metodi di istanza definiti in Rake, quindi puoi farlo

Rake.run_tests

23

Per me aiuta sempre pensare extendcome includeall'interno della classe singleton (nota anche come classe meta o eigen).

Probabilmente sai che i metodi definiti all'interno della classe singleton sono fondamentalmente metodi di classe:

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

A.x #=> 'x'

Ora che sappiamo che, extendavranno includei metodi del modulo all'interno della classe Singleton e quindi esporli come metodi di classe:

module A
  class << self
    include A

    def x
      puts 'x'
    end
  end

  def y
    puts 'y'
  end
end

A.x #=> 'x'
A.y #=> 'y'

15

Per evitare la decomposizione dei collegamenti, il post sul blog di Chris Wanstrath collegato da user83510 viene ripubblicato di seguito (con il suo permesso). Tuttavia, niente è meglio di un originale, quindi usa il suo collegamento finché continua a funzionare.


→ Singin 'singleton 18 novembre 2008 Ci sono cose che proprio non capisco. David Bowie, per esempio. O l'emisfero australe. Ma niente mi sbalordisce come Ruby's Singleton. Perché davvero, è totalmente inutile.

Ecco cosa vogliono che tu faccia con il tuo codice:

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'

Ma è pazzesco. Combatti il ​​potere.

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'

Qualunque perché no? L'API è più concisa, il codice è più facile da testare, simulare e stub ed è ancora semplicissimo convertirlo in una classe appropriata in caso di necessità.

((copyright dovrebbe ten chris wanstrath))


Un altro modo per evitare linkrot è usare qualcosa come la macchina del ritorno - web.archive.org - mantiene una cronologia delle pagine sul web, l'ho trovato comunque molto utile in molti casi di linkrot.
Kem Mason

3

extend selfinclude tutti i metodi di istanza esistenti come metodi di modulo. Questo equivale a dire extend Rake. Inoltre Rakeè un oggetto di classe Module.

Un altro modo per ottenere un comportamento equivalente sarà:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

Può essere utilizzato per definire moduli autonomi con metodi privati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.