17 Stimmen

Was sind einige gute Beispiele für Mixins und Traits?

Ich war das Lesen auf Ruby, und lernte über seine Mixins Muster, konnte aber nicht denken, von vielen nützlichen Mixin-Funktionalität (weil ich nicht verwendet werden, um diese Art und Weise wahrscheinlich zu denken). Also habe ich mich gefragt, was wären gute Beispiele für nützliche Mixin-Funktionalität?

Danke

Bearbeiten: Ein wenig Hintergrund. Ich komme aus C++ und anderen Objektsprachen, aber mein Zweifel ist, dass Ruby sagt, dass es keine Mixins vererbt, aber ich sehe immer wieder Mixins als Mehrfachvererbung, also fürchte ich, dass ich versuche, sie zu früh in meiner Komfortzone zu kategorisieren und nicht wirklich weiß, was ein Mixin ist.

13voto

Jon Wood Punkte 2589

Sie werden in der Regel verwendet, um einer Klasse eine Art von Standardfunktionalität hinzuzufügen, ohne sie komplett neu definieren zu müssen. Man kann sie sich wahrscheinlich ein bisschen wie Schnittstellen in Java vorstellen, aber anstatt nur eine Liste von Methoden zu definieren, die implementiert werden müssen, werden viele von ihnen tatsächlich sein durch Einbindung des Moduls implementiert.

Es gibt einige Beispiele in der Standardbibliothek:

Singleton - Ein Modul, das in jede Klasse gemischt werden kann, um sie zu einem Singleton zu machen. Die Initialisierungsmethode wird privat gemacht und eine Instanzmethode hinzugefügt, die sicherstellt, dass es immer nur eine Instanz dieser Klasse in Ihrer Anwendung gibt.

Comparable - Wenn Sie dieses Modul in eine Klasse einbinden, genügt die Definition der <=>-Methode, die die aktuelle Instanz mit einem anderen Objekt vergleicht und angibt, welches größer ist, um die Methoden <, <=, ==, >=, > und between? bereitzustellen.

Enumerable - Durch Einmischen dieses Moduls und Definition eines jede Methode erhalten Sie Unterstützung für alle anderen verwandten Methoden wie collect, inject, select und reject. Wenn es auch die <=>-Methode hat, dann unterstützt es auch sort, min und max.

DataMapper ist auch ein interessantes Beispiel dafür, was man mit einer einfachen Include-Anweisung machen kann, indem man eine Standardklasse nimmt und die Fähigkeit hinzufügt, sie in einem Datenspeicher zu persistieren.

11voto

Gishu Punkte 130442

Das übliche Beispiel ist wohl Persistenz

module Persistence
    def load sFileName
            puts "load code to read #{sFileName} contents into my_data"
    end
        def save sFileName
        puts "Uber code to persist #{@my_data} to #{sFileName}"
    end

end

class BrandNewClass
    include Persistence
    attr :my_data

        def data=(someData)
        @my_data = someData
    end
end

b = BrandNewClass.new
b.data = "My pwd"
b.save "MyFile.secret"
b.load "MyFile.secret"

Stellen Sie sich vor, das Modul wird von einem Ruby-Ninja geschrieben, der den Zustand Ihrer Klasse in einer Datei festhält.
Angenommen, ich schreibe eine brandneue Klasse, kann ich die Funktionalität der Persistenz wiederverwenden, indem ich sie einmische, indem ich sage include ModuleILike . Sie können sogar Module zur Laufzeit einbinden. Ich erhalte Lade- und Speichermethoden kostenlos, indem ich sie einfach einmische. Diese Methoden sind genau wie die, die Sie selbst für Ihre Klasse geschrieben haben. Code/Verhaltensweisen/Funktionalität - Wiederverwendung ohne Vererbung!

Was Sie also tun, ist, Methoden in die Methodentabelle Ihrer Klasse aufzunehmen (nicht wörtlich korrekt, aber nahe dran).

3voto

rampion Punkte 84270

In Ruby sind Mixins nicht mehrfach vererbbar, weil das Kombinieren von Mixin-Methoden eine einmalige Sache ist. Das wäre kein so großes Problem, außer dass die Module und Klassen von Ruby offen für Änderungen sind. Das heißt, wenn du ein Modul in deine Klasse mixinst und dann eine Methode zu dem Modul hinzufügst, wird die Methode wird nicht für Ihre Klasse zur Verfügung stehen, während es bei umgekehrter Reihenfolge der Fall wäre.

Das ist so, als würde man eine Eistüte bestellen. Wenn Sie Schokoladenstreusel und Toffee-Stückchen als Zutaten wählen und mit Ihrer Eiswaffel weggehen, ändert sich die Art der Eiswaffel nicht, wenn jemand in der Eisdiele bunte Streusel in den Behälter mit den Schokoladenstreuseln gibt. Ihre Klasse, die Eistüte, wird nicht verändert, wenn das Mixin-Modul, der Behälter mit Streuseln, verändert wird. Die nächste Person, die das Mixin-Modul verwendet, wird die Änderungen sehen.

Wenn Sie include ein Modul in Ruby, ruft es Module#append_features auf dieses Modul, die eine Kopie der Methoden dieses Moduls einmalig in den Includer einfügen.

Mehrfachvererbung ist, so wie ich es verstehe, eher eine Art Delegation. Wenn Ihre Klasse nicht weiß, wie sie etwas tun soll, fragt sie ihre Eltern. In einer Open-Class-Umgebung können die Eltern einer Klasse geändert worden sein, nachdem die Klasse erstellt wurde.

Es ist wie eine RL-Eltern-Kind-Beziehung. Deine Mutter hat vielleicht erst nach deiner Geburt gelernt zu jonglieren, aber wenn dich jemand darum bittet und du sie bittest, dir entweder zu zeigen, wie es geht (es zu kopieren, wenn du es brauchst) oder es für dich zu tun (reine Delegation), dann ist sie zu diesem Zeitpunkt dazu in der Lage, auch wenn du vor ihrer Fähigkeit zu jonglieren erschaffen wurdest.

Es ist möglich, ein Ruby-Modul 'include' so zu modifizieren, dass es sich eher wie Mehrfachvererbung verhält, indem man die Module#append_features um eine Liste der Einbindungen zu führen und sie dann mit der Option method_added Callback, aber das wäre eine große Abweichung vom Standard-Ruby und könnte zu großen Problemen bei der Arbeit mit anderem Code führen. Es könnte besser sein, einen Module#inherit Methode, die die include und auch die Delegation.

Ein Beispiel aus der Praxis, Enumerable ist großartig. Wenn Sie definieren #each und umfassen Enumerable in Ihrer Klasse, dann haben Sie Zugriff auf eine ganze Reihe von Iteratoren, ohne dass Sie jeden einzelnen programmieren müssen.

1voto

J Cooper Punkte 16641

Sie wird weitgehend so verwendet, wie man Mehrfachvererbung in C++ oder die Implementierung von Schnittstellen in Java/C# verwenden könnte. Ich bin mir nicht sicher, wo Ihre Erfahrung liegt, aber wenn Sie diese Dinge bereits getan haben, sind Mixins die Art und Weise, wie Sie sie in Ruby tun würden. Es ist eine systematisierte Art, Funktionalität in Klassen einzubringen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X