Ruby: Selbst erweitern


113

In Ruby verstehe ich die Grundidee von extend. Was passiert jedoch in diesem Codesegment? Was macht konkret extend? Ist es nur eine bequeme Möglichkeit, die Instanzmethoden in Klassenmethoden umzuwandeln? Warum sollten Sie dies so tun, anstatt von Anfang an Klassenmethoden anzugeben?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

Antworten:


115

Es ist eine bequeme Möglichkeit, Instanzmethoden in Klassenmethoden umzuwandeln. Sie können es aber auch als effizienteren Singleton verwenden .


2
Warum ist diese Art von Singleton effizienter?
Xuuso

5
Dein Link hat meinen Freund verdorben.
Ulysse BN

1
Aktualisiert diese Antwort mit einem Link zu archive.org
Mike Szyndel

1
Diese Antwort ist unzureichend, da sie nicht erklärt, wie das betreffende Schlüsselwort Instanzmethoden zu Klassenmethoden macht. Es erklärt auch nicht, was ein "effizienterer Singleton" ist oder was extend selfdamit zu tun hat.
Jayqui

29

In einem Modul ist self die Modulklasse selbst. So zum Beispiel

puts self

wird Rake so zurückgeben,

extend self

Grundsätzlich stehen ihm die in Rake definierten Instanzmethoden zur Verfügung, damit Sie dies tun können

Rake.run_tests

23

Für mich ist es immer hilft , zu denken , extendwieinclude innerhalb der Singleton-Klasse (auch als Meta oder Eigenklasse bekannt) zu betrachten.

Sie wissen wahrscheinlich, dass in der Singleton-Klasse definierte Methoden im Grunde Klassenmethoden sind:

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

A.x #=> 'x'

Jetzt, da wir das wissen, extendwerden includedie Methoden im Modul innerhalb der Singleton-Klasse und damit als Klassenmethoden verfügbar gemacht:

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

Um Link Rot zu vermeiden, wird der von user83510 verlinkte Blog-Beitrag von Chris Wanstrath unten (mit seiner Erlaubnis) erneut veröffentlicht. Trotzdem ist nichts besser als ein Original. Verwenden Sie seinen Link, solange er funktioniert.


→ Singletons singen 18. November 2008 Es gibt Dinge, die ich einfach nicht verstehe. David Bowie zum Beispiel. Oder die südliche Hemisphäre. Aber nichts verwirrt mich so sehr wie Rubys Singleton. Weil es wirklich völlig unnötig ist.

Folgendes sollen Sie mit Ihrem Code tun:

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'

Aber das ist verrückt. Kämpfe gegen die Macht.

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'

Warum nicht? Die API ist prägnanter, der Code ist einfacher zu testen, zu verspotten und zu stubben, und es ist immer noch kinderleicht, ihn bei Bedarf in eine richtige Klasse zu konvertieren.

((Copyright sollte zehn Chris Wanstrath)


Eine andere Möglichkeit, Linkrot zu vermeiden, besteht darin, so etwas wie die Wayback-Maschine - web.archive.org - zu verwenden. Sie führt einen Verlauf von Seiten im gesamten Web. Ich fand es in vielen Fällen von Linkrot sowieso sehr hilfreich.
Kem Mason

3

extend selfEnthält alle vorhandenen Instanzmethoden als Modulmethoden. Dies ist gleichbedeutend mit sagen extend Rake. Ist auch Rakeein Objekt der Klasse Module.

Ein anderer Weg, um ein gleichwertiges Verhalten zu erreichen, ist:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

Dies kann verwendet werden, um eigenständige Module mit privaten Methoden zu definieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.