Ruby: rozszerz siebie


113

W Rubim rozumiem podstawową ideę extend. Jednak co się dzieje w tym segmencie kodu? A konkretnie, co robi extend? Czy jest to tylko wygodny sposób przekształcenia metod instancji w metody klasowe? Dlaczego miałbyś to robić w ten sposób, zamiast określać metody klas od początku?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

Odpowiedzi:


115

Jest to wygodny sposób przekształcania metod instancji w metody klasowe. Ale możesz też użyć go jako bardziej wydajnego singletona .


2
Dlaczego taki singleton jest bardziej wydajny?
xuuso

5
Twój link zgnił mojego przyjaciela.
Ulysse BN,

1
Zaktualizowałem tę odpowiedź linkiem do archive.org
Mike Szyndel

1
Ta odpowiedź jest niewystarczająca, ponieważ nie wyjaśnia, w jaki sposób dane słowo kluczowe przekształca metody instancji w metody klas. Nie wyjaśnia też, czym jest „bardziej wydajny singleton” ani co extend selfma z tym wspólnego.
jayqui

29

W module self jest samą klasą modułu. Na przykład

puts self

zwróci Rake, więc

extend self

zasadniczo udostępnia metody instancji zdefiniowane w Rake, więc możesz to zrobić

Rake.run_tests

23

Dla mnie to zawsze pomaga myśleć extendjak includewewnątrz klasy singleton (znany również jako meta lub EIGEN klasie).

Zapewne wiesz, że metody zdefiniowane w klasie singleton są w zasadzie metodami klasowymi:

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

A.x #=> 'x'

Teraz, gdy wiemy, że extendbędą includemetody w module wewnątrz klasy singleton, a tym samym narazić je jako metody klasy:

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

Aby uniknąć gnicia linków, poniżej opublikowano ponownie post Chrisa Wanstratha, do którego prowadzi user83510 (za jego zgodą). Jednak nic nie przebije oryginału, więc używaj jego linku tak długo, jak będzie działać.


→ singin 'singletons 18 listopada 2008 Są rzeczy, których po prostu nie rozumiem. Na przykład David Bowie. Albo na półkuli południowej. Ale nic tak nie zadziwia mnie jak Singleton Ruby. Bo naprawdę, to zupełnie niepotrzebne.

Oto, co chcą, abyś zrobił ze swoim kodem:

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'

Ale to jest szalone. Walcz z mocą.

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'

Każdy, dlaczego nie? Interfejs API jest bardziej zwięzły, kod jest łatwiejszy do testowania, makiety i odgałęzienia, a konwersja na odpowiednią klasę w razie potrzeby jest nadal bardzo prosta.

((prawa autorskie powinny mieć ten Chris Wanstrath))


Innym sposobem uniknięcia linkrot jest użycie czegoś w rodzaju wayback machine - web.archive.org - przechowuje historię stron w sieci, i tak uznałem to za bardzo pomocne w wielu przypadkach linkrot.
Kem Mason

3

extend selfobejmuje wszystkie istniejące metody instancji jako metody modułu. To jest równoznaczne z powiedzeniem extend Rake. Również Rakejest obiektem klasy Module.

Innym sposobem uzyskania równoważnego zachowania będzie:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

Może to służyć do definiowania samodzielnych modułów z prywatnymi metodami.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.