2008-12-10 11 views
14

Ich habe Ruby gelesen und etwas über sein Mixins-Muster gelernt, aber ich konnte mir nicht viele nützliche Mix-Funktionen vorstellen (weil ich es nicht gewohnt bin, so zu denken). Also habe ich mich gefragt, was wären gute Beispiele für nützliche Mixin-Funktionalität?Was sind gute Beispiele für Mixins und/oder Traits?

Danke

Edit: Ein bisschen Hintergrund. Ich komme aus C++ und anderen Object-Sprachen, aber meine Zweifel hier ist, dass Ruby sagt, dass es Mixins nicht erbt, aber ich sehe Mixins immer als Multiple-Vererbung, also habe ich Angst, sie zu früh in meine Komfortzone einzuordnen und nicht wirklich, was für ein Mixin ist.

+2

Es ist lustig zu sehen, dass die [Sprache-agnostic] und [Ruby] -Tags direkt nebeneinander sitzen wie sie beste Freunde sind =) – Oli

+1

gut Ruby löste die Frage, aber Mixin und Züge können in anderen Sprachen gemacht werden, als es ist eher ein Muster Ich denke, –

Antwort

8

Nun das übliche Beispiel, das ich denke, ist 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 das Modul durch ein Ruby-ninja geschrieben ist, die den Zustand Ihrer Klasse in einer Datei bestehen bleibt.
Nun nehme ich an, ich schreibe eine brandneue Klasse, ich kann die Funktionalität der Persistenz wiederverwenden, indem ich sie mit include ModuleILike kombiniere. Sie können sogar Module zur Laufzeit hinzufügen. Ich lade und spare Methoden kostenlos, indem ich sie einfach rein mische. Diese Methoden sind genau wie die, die Sie selbst für Ihre Klasse geschrieben haben. Code/Verhalten/Funktionalität - Wiederverwendung ohne Vererbung!

Also was Sie tun, ist Methoden in die Methodentabelle für Ihre Klasse (nicht wörtlich korrekt, aber schließen).

+0

Das scheint eine nützliche Verwendung. Klingt gut. –

1

Es wird weitgehend verwendet, da man in C++ mehrere Vererbungen verwenden oder Schnittstellen in Java/C# implementieren kann. Ich bin mir nicht sicher, wo deine Erfahrung liegt, aber wenn du diese Dinge schon einmal gemacht hast, dann mixt man sie in Ruby. Es ist eine systematisierte Möglichkeit, Funktionalität in Klassen zu injizieren.

+1

Kommend von C++, und andere, aber meine Zweifel hier ist, dass Ruby sagt, es erbt nicht Mixins, aber ich sehe Mixins als Multiple Vererbung genau wie du sagst, so fürchte ich, ich versuche zu kategorisieren sie zu früh in meine Komfortzone, und nicht wirklich grok was ein Mixin ist. –

12

Sie werden normalerweise verwendet, um einer Klasse irgendeine Form von Standardfunktionalität hinzuzufügen, ohne alles neu definieren zu müssen. Sie können sie wahrscheinlich ein wenig wie Schnittstellen in Java denken, aber anstatt nur eine Liste von Methoden zu definieren, die implementiert werden müssen, werden viele von ihnen implementiert, indem Sie das Modul einbeziehen.

Es gibt einige Beispiele in der Standardbibliothek:

Singleton - Ein Modul, das in jeder Klasse gemischt werden kann, um es ein Singleton zu machen. Die initialize -Methode wird als private definiert und eine Instanzmethode hinzugefügt, die sicherstellt, dass nur eine Instanz dieser Klasse in Ihrer Anwendung vorhanden ist.

Vergleichbar - Wenn Sie sind dieses Modul in einer Klasse, die Definition der < => Methode, die die aktuelle Instanz mit einem anderen Objekt vergleicht und sagt, die größer ist, ist genug < zu schaffen, < =, ==,> = ,> und zwischen? Methoden.

Enumerable - Durch Mischen in diesem Modul und Definieren einer Methode erhalten Sie Unterstützung für alle anderen verwandten Methoden wie Sammeln, injizieren, auswählen und ablehnen. Wenn es auch die < => Methode hat, wird es auch sort, min und max unterstützen.

DataMapper ist auch ein interessantes Beispiel dafür, was mit einer einfachen Include-Anweisung getan werden kann, indem eine Standardklasse verwendet wird und die Möglichkeit hinzugefügt wird, sie in einem Datenspeicher zu speichern.

3

In Ruby ist der Grund, dass Mixins keine Mehrfachvererbung sind, dass die Kombination von Mixin-Methoden eine einmalige Sache ist.Dies wäre kein so großes Problem, außer dass die Module und Klassen von Ruby offen sind für Änderungen. Dies bedeutet, dass wenn Sie ein Modul zu Ihrer Klasse hinzufügen und dann eine Methode zum Modul hinzufügen, die Methode nicht für Ihre Klasse verfügbar ist; Wenn du es in umgekehrter Reihenfolge machst, würdest du es tun.

Es ist wie eine Eistüte zu bestellen. Wenn du Schokostreusel und Toffeestückchen als deine Mixins bekommst und mit deinem Kegel weggehst, was für eine Eistüte du hast, wird sich nicht ändern, wenn jemand mehrfarbige Streusel in die Schokostreusel-Kiste in der Eisdiele gibt. Ihre Klasse, die Eistüte, wird nicht verändert, wenn das Mixin-Modul, der Bin der Streusel, ist. Die nächste Person, die dieses Mixmodul verwendet, sieht die Änderungen.

Wenn Sie include ein Modul in Ruby, ruft es Module#append_features auf diesem Modul, die eine Kopie der Methoden dieses Moduls zum Includer einmal hinzufügen.

Mehrfachvererbung, wie ich es verstehe, ist eher wie Delegation. Wenn deine Klasse nicht weiß, wie sie etwas tun soll, fragt sie ihre Eltern. In einer offenen Klassenumgebung wurden die übergeordneten Elemente einer Klasse möglicherweise geändert, nachdem die Klasse erstellt wurde.

Es ist wie eine RL Eltern-Kind-Beziehung. Vielleicht hat deine Mutter gelernt, wie man jongliert, nachdem du geboren wurdest, aber wenn dich jemand bittet, zu jonglieren, und du sie entweder darum bittest: zeige dir wie (kopiere es, wenn du es brauchst) oder tu es für dich (reine Delegation), dann sie Ich werde zu diesem Zeitpunkt in der Lage sein, obwohl Sie erstellt wurden, bevor sie jonglieren konnte.

Es ist möglich, dass Sie ein Rubin-Modul ändern könnten ‚umfassen‘ mehr wie Mehrfachvererbung zu handeln, indem Module#append_features Modifizieren eine Liste von includers zu halten, und dann den method_added Rückruf mit ihnen zu aktualisieren, aber das ist eine große Verschiebung wäre aus Standard-Ruby, und könnte bei der Arbeit mit anderen Code große Probleme verursachen. Sie könnten besser eine Module#inherit Methode erstellen, die include aufgerufen und Delegierung behandelt.

Wie für ein reales Beispiel ist Enumerable genial. Wenn Sie in Ihrer Klasse #each definieren und Enumerable in Ihre Klasse aufnehmen, dann haben Sie damit Zugriff auf eine ganze Reihe von Iteratoren, ohne dass Sie jede einzelne programmieren müssen.

+1

Vielleicht verstehe ich Ihren Punkt falsch oder vielleicht hat sich Ruby seit Dezember 2008 geändert, aber der folgende Code zeigt nicht das "einmalige" Verhalten, das Sie beschreiben. Beachten Sie insbesondere, dass die 'Foo'-Instanz in der Lage ist, die' fubb'-Methode aufzurufen, obwohl diese Methode dem 'Mixin'-Modul * hinzugefügt wurde, nachdem * die' Foo'-Klasse im Modul gemischt wurde. Der Beispielcode (mit Semikolons zur Darstellung von Zeilenumbrüchen): 'Modul Mixin; def bar; setzt "Mixin.bar()"; Ende; Ende; Klasse Foo; schließen Mixin ein; Ende; Modul Mixin; def fubb; setzt "Mixin.fubb()"; Ende; Ende; f = Foo.new; f.bar; f.fubb'. – FMc

+0

Ordentlich! Ich schätze, ich liege jetzt falsch. Gut zu wissen, danke! – rampion

+1

Wenn Sie denken, dass Sie falsch liegen, können Sie Ihre Antwort bearbeiten und mindestens eine Notiz hinzufügen, um die Kommentare zu lesen? Vielen Dank! – wbyoung

Verwandte Themen