Frage

Just getting my head around Ruby metaprogramming.Mixins/Module immer gelingt, verwirren mich.

  • gehören:mischt sich in das angegebene Modul Methoden Instanz-Methoden in der Ziel-Klasse
  • verlängern:mischt sich in das angegebene Modul Methoden Klassenmethoden in der Ziel-Klasse

So ist der wesentliche Unterschied gerade dies oder ist eine größere Drachen lauern? z.B.

module ReusableModule
  def module_method
    puts "Module Method: Hi there!"
  end
end

class ClassThatIncludes
  include ReusableModule
end
class ClassThatExtends
  extend ReusableModule
end

puts "Include"
ClassThatIncludes.new.module_method       # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method            # "Module Method: Hi there!"
War es hilfreich?

Lösung

Was Sie gesagt haben, ist richtig. Allerdings gibt es mehr als das.

Wenn Sie eine Klasse Klazz und Modul Mod, einschließlich Mod in Klazz gibt Fälle von Klazz Zugriff auf Mod Methoden. Oder Sie können Klazz mit Mod geben die Klasse Klazz Zugriff auf Mod Methoden erweitern. Aber auch Sie können ein beliebiges Objekt mit o.extend Mod erweitern. In diesem Fall wird das einzelne Objekt bekommt Methoden des Mod obwohl alle andere Objekte mit der gleichen Klasse wie o dies nicht tun.

Andere Tipps

erweitern - fügt die Methoden des angegebenen Moduls und Konstanten des Ziels metaclass (das heißt die Singleton-Klasse)   z.B.

  • , wenn Sie Klazz.extend(Mod) anrufen, jetzt Klazz hat Mod Methoden (als Klassenmethoden)
  • , wenn Sie obj.extend(Mod) anrufen, jetzt obj hat Mod Methoden (wie zB Methoden), aber keine andere Instanz von obj.class diese Methoden hinzugefügt.
  • extend ist eine öffentliche Methode

ist - Standardmäßig mischt es in der Methoden des angegebenen Moduls als Instanzmethoden in der Ziel Modul / Klasse.   z.

  • , wenn Sie class Klazz; include Mod; end; nennen, jetzt alle Instanzen von Klazz Zugriff auf Methoden der Mod haben (wie zB Methoden)
  • include ist eine private Methode, weil es beabsichtigt ist aus dem Container-Klasse / Modul aufgerufen werden.

Doch , Module sehr häufig Überschreibung include Verhalten von Affen Patchen die included Methode. Dies ist sehr prominent in Legacy-Rails-Code. mehr Details von Yehuda Katz .

Weitere Informationen über include mit seinem Standardverhalten, vorausgesetzt, Sie haben den folgenden Code ausführen

class Klazz
  include Mod
end
  • Wenn Mod bereits in Klazz enthalten ist, oder einer seiner Vorfahren, die Include-Anweisung hat keine Auswirkung
  • Es enthält auch Mod Konstanten in Klazz, solange sie es nicht tun kollidieren
  • Es gibt Klazz Zugriff auf Mod-Modul Variablen, zum Beispiel @@foo oder @@bar
  • hebt Argument wenn es zyklisch enthält
  • Hängt das Modul als die unmittelbaren Vorfahren des Anrufers (dh es Mod Klazz.ancestors fügt hinzu, aber Mod ist nicht auf die Kette von Klazz.superclass.superclass.superclass hinzugefügt. So wird prüfen Mod super in Klazz # foo Aufruf #foo vor dem Klazz wirklicher Superklasse foo Methode zu überprüfen. Siehe RubySpec für weitere Details.).

Natürlich die Dokumentation Rubin Kern ist immer der beste Ort, um gehen für diese Dinge. Das RubySpec Projekt auch eine fantastische Ressource war, weil sie die Funktionalität genau dokumentiert.

Das ist richtig.

Hinter den kulissen enthalten ist, ist eigentlich ein alias für append_features, der (aus der Dokumentation):

Ruby ' s Standard-Ausführung fügen Sie den Konstanten, Methoden und module Variablen dieses Modul aModule, wenn dieses Modul nicht bereits Hinzugefügt wurde zu aModule oder einer seiner Vorfahren.

Alle anderen Antworten sind gut, einschließlich der Spitze durch RubySpecs zu graben:

https://github.com/rubyspec/rubyspec/ Blob / Master / core / module / include_spec.rb

https://github.com/rubyspec/rubyspec/ Blob / Master / core / module / extend_object_spec.rb

Wie für Anwendungsfälle:

Wenn Sie sind Modul ReusableModule in Klasse ClassThatIncludes, die Methoden, Konstanten, Klassen, Submodule und andere Erklärungen wird verwiesen.

Wenn Sie erweitern Klasse ClassThatExtends mit Modul ReusableModule, dann werden die Methoden und Konstanten wird kopiert . Natürlich, wenn Sie nicht vorsichtig sind, können Sie eine Menge Speicher verschwenden, indem dynamisch Definitionen zu duplizieren.

Wenn Sie Active :: Sorge verwenden, die .included () Funktionalität können Sie die mit Klasse direkt umschreiben. Modul Class innen ein Anliegen bekommt erweitert (kopiert) in die darunter Klasse.

Ich möchte auch den Mechanismus erklären, wie es funktioniert. Wenn ich richtig bin nicht bitte korrigieren.

Wenn wir verwenden include wir eine Verknüpfung von unserer Klasse zu einem Modul hinzufügen, die einige Methoden enthält.

class A
include MyMOd
end

a = A.new
a.some_method

Objekte Methoden nicht haben, nur clases und Module tun. Also, wenn a Mésage empfängt some_method es Suchmethode some_method in a der Eigen Klasse beginnen, dann in A Klasse und dann verknüpfen in Klassenmodulen A wenn es einige gibt (in umgekehrter Reihenfolge, zuletzt gewinnt enthalten).

Wenn wir verwenden extend wir Verknüpfung mit einem Modul in Objekteigen Klasse hinzufügen. Also, wenn wir verwenden A.new.extend (MyMod) wir Bindung an unser Modul A der Instanz Eigen Klasse oder a' Klasse hinzufügen. Und wenn wir A.extend (MyMod) verwenden wir das Hinzufügen Verknüpfung zu A (Objekt, Klassen sind auch Objekte) Eigenklasse A'.

so Methodennachschlag Weg für a ist wie folgt: a => a '=> Module zu einem verknüpften' class => A.

Auch gibt es eine Methode, die prepend Lookup Pfad ändert:

a => a‘=> vorangestellt modulesto A => A => enthalten Modul A

sorry für mein schlechtes Englisch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top