Ruby: Klasse C enthält Modul M; einschließlich Modul N in M ​​beeinflusst nicht C. Was gibt?

8

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 .

Beispiel:

%Vor%     
kch 31.10.2009, 20:59
quelle

3 Antworten

2

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.

%Vor%

Verallgemeinern wir nun:

%Vor%

Jetzt auf GitHub und Gemcutter für zusätzlichen Spaß.

    
kch 31.10.2009, 21:11
quelle
3

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.

    
sepp2k 31.10.2009 21:10
quelle
3

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.

    
Rishav Rastogi 31.10.2009 21:09
quelle

Tags und Links