Genauer gesagt, ich habe ein Modul Narf
, das einer Reihe von Klassen wesentliche Funktionen zur Verfügung stellt. Insbesondere möchte ich alle Klassen beeinflussen, die Enumerable
erben. Also ich include Narf
in Enumerable
.
Array
ist eine Klasse, die standardmäßig Enumerable
enthält. Es ist jedoch nicht von der späten Aufnahme von Narf
in das Modul betroffen.
Interessanterweise erhalten Klassen, die nach der Aufnahme definiert wurden, Narf
von Enumerable
.
Beim Schreiben meiner Frage, unweigerlich, stieß ich auf eine Antwort. Folgendes habe ich mir ausgedacht. Lassen Sie mich wissen, ob ich eine offensichtliche, viel einfachere Lösung verpasst habe.
Das Problem scheint zu sein, dass eine Moduleinbindung die Vorfahren des enthaltenen Moduls flacht und das enthält. Daher ist das Methoden-Lookup nicht vollständig dynamisch, die Ahnenkette der enthaltenen Module wird niemals überprüft.
In der Praxis ist Array
weiß Enumerable
ein Vorgänger, aber es ist nicht wichtig, was aktuell in Enumerable
enthalten ist.
Die gute Sache ist, dass Sie include
modules wieder können, und es wird die Modul-Vorfahrenkette neu berechnen und die ganze Sache einschließen. Nachdem Sie also Narf
definiert und eingeschlossen haben, können Sie Array
erneut öffnen und Enumerable
erneut einschließen, und es wird auch Narf
angezeigt.
Verallgemeinern wir nun:
%Vor%Es gibt zwei Fixes zu deinem Problem, die dir in den Sinn kommen. Keiner von ihnen ist wirklich hübsch:
a) Gehen Sie alle Klassen durch, die Enumerable enthalten, und machen Sie sie auch zu Narf. Etwas wie das:
%Vor%Das ist aber ziemlich hackisch.
b) Fügen Sie die Funktionalität direkt zu Enumerable statt zu ihrem eigenen Modul hinzu. Dies könnte tatsächlich in Ordnung sein und es wird funktionieren. Dies ist der Ansatz, den ich empfehlen würde, obwohl es auch nicht perfekt ist.
class Array wurde bereits mit dem Enumerable-Modul gemischt, das Ihr Narf-Modul noch nicht enthält. Das ist der Grund, warum es einen (im Wesentlichen seine Methoden) n Fehler wirft.
Wenn Sie Enumerable in Array erneut einschließen, z. B.
%Vor%Ein Mix-In erstellt einen Verweis von der Klasse auf das enthaltene Modul, in dem in diesem speziellen Objektraum alle Methoden enthalten sein müssen. Wenn Sie eine der vorhandenen Methoden eines Moduls ändern, spiegeln alle Klassen, die das Modul enthalten, die Änderungen wider.
Wenn Sie dem bereits vorhandenen Modul jedoch ein neues Modul hinzufügen, müssen Sie das Modul erneut einfügen, damit der Verweis aktualisiert werden kann.