Ich habe eine verschachtelte Struktur von Modulen, die nur für Namespacing-Zwecke verwendet werden; kein Mischen in Klassen usw. Also habe ich einen Code wie folgt:
%Vor% Nun nehme ich an, ich möchte eine weitere Hilfsmethode im Modul A
hinzufügen, und ich möchte, dass sie von beiden Modulen einfach verwendet werden kann. Ich bekomme Folgendes:
und es scheint zu funktionieren, aber es hat einige Nachteile, die ich gerne loswerden möchte:
Ich möchte helper
nicht immer mit dem voll qualifizierten Namen ( A::helper
) von B
aus aufrufen. Am liebsten würde ich Ruby sagen, dass dieses Namensraum-Präfix "Standard" ist und einfach als helper
bezeichnet wird. In C ++ könnte ich einfach using A::helper
in den Namespace B
schreiben und es würde das Problem lösen. Aber wie geht es in Ruby?
Ich habe versucht, include A
und extend A
in B
hinzuzufügen, aber keiner von ihnen funktioniert. Sie scheinen nur in Klassen zu funktionieren, wenn diese Module gemischt sind, aber nicht, wenn sie eigenständig sind und nur für Namespacing-Zwecke verwendet werden.
Gibt es andere Möglichkeiten, damit es so funktioniert, wie ich es möchte?
Oh, und noch eins:
Angenommen, ein anderes Szenario, bei dem A::helper
nur von den Methoden von A
verwendet werden soll, weil es nur eine Implementationsfunktion ist, wo ich einen gemeinsamen Code, der von vielen Funktionen in A
verwendet wird, jetzt ausklammere Ich will nicht, dass es für die Außenwelt sichtbar ist, nur um die Methoden von A
. Wie kann ich es tun?
Ich habe versucht mit module_function
+ das A.
Präfix von allen anderen Funktionen zu entfernen, die versteckt werden sollen, aber dann sind sie auch für andere Methoden in A
versteckt, weil sie dann Instanzmethoden sind, und Module können nicht instanziiert werden. Wie kann ich also eine Modulmethode vor der Außenwelt verbergen und trotzdem für die interne Verwendung durch andere Modulmethoden zulassen?
Bearbeiten Warum downvoting? Ich habe versucht, so klar wie möglich zu sein, dass ich einen Namespace in einem anderen Namespace standardmäßig auf setzen muss, um lange vollständig qualifizierte Namen vollständig zu entfernen (nicht nur Aliasing) sie zu etwas kürzerem), und dass mein Problem nicht Klassen & amp betrifft; Objekte überhaupt, nur einfache Module, die nur für Namespacing-Zwecke verwendet werden. Wie sonst könnte ich es erklären?
Es ist nicht mein Fehler, dass Namespacing-Mechanismen anscheinend nicht vollständig in Ruby nativ wie in Sprachen wie C ++ unterstützt werden und dass es nur ein zu sein scheint Nebeneffekt der Verwendung von Modulen und Klassen, um einige Funktionen von echten Namespaces zu haben (sie quaken wie Enten, sie haben Ducky Beaks, aber sie sind Schnabeltiere, keine Enten und sollten nicht als Namespaces beworben werden, die sie anscheinend nicht sind, weil es nur Leute verwirrt, die von anderen Sprachen mit echten Namespaces zu Ruby kommen), oder dass Sie Konzepte aus anderen Programmiersprachen anscheinend nicht verstehen, wenn sie nicht einfach möglich sind in Ruby (da ich sehe, dass du scheinst so zu tun, als ob mein Problem nicht existiert und zu dem zurückgehe, was du in Ruby leicht machen kannst, aber das brauche ich nicht).
>Und warum wurde die einzige Antwort, die für meine Frage relevant war, gelöscht? Nicht cool ;.
OK, da die einzige Antwort, die für meine Frage relevant war, gelöscht wurde, werde ich versuchen, meine Frage selbst zu beantworten, basierend auf der gelöschten Antwort von @sawa (Danke an @sawa für die Andeutung in die richtige Richtung) . Ich habe es etwas modifiziert, um meinen Bedürfnissen besser zu entsprechen und eleganter zu sein. Später werde ich beschreiben, warum die ursprüngliche @ sawas Antwort nicht das war, wonach ich gesucht habe.
OK, also ohne weitere Umschweife, hier ist mein eigener Lösungsversuch:
So funktioniert es:
Zunächst einmal definiert es alle seine Methoden als Instanzmethoden der jeweiligen Modulklasse selbst ( A
in diesem Fall). Aber dann, um sie für den externen Gebrauch verfügbar zu machen, ohne zu instantiieren (was schließlich für Module unmöglich ist), ich extend
das A
Modul mit sich selbst, was diese Methoden auch zu seinen Klassenmethoden macht. Da sie aber auch Instanzmethoden des Moduls A
sind, können sie von innerhalb anderer Methoden dieses Moduls aufgerufen werden, ohne dass ihnen der Modulname vorangestellt wird. Dasselbe gilt für das Modul B
, das sich auch extend
mit den Methoden des Moduls A
zu eigen macht. Dann kann ich sie auch in B
's Methoden ohne Präfix aufrufen, so wie ich es wollte.
Wie Sie sehen können, kann ich nicht nur die Methoden beider Module von außen aufrufen, als ob sie die Methoden ihrer Klasse wären, und ich kann A::helper
von B::foo
aufrufen, ohne ihren Namen vollständig zu qualifizieren, aber ich kann auch anrufen A::foo
von A::helper
ohne Qualifizierung. Dies ist genau das, was ich brauchte und scheint zu funktionieren, wie ich es erwartet habe.
Das einzige Problem bei diesem Ansatz könnte darin liegen, dass sich ihre Schnittstellen vermischen. In B
ist das kein großes Problem, da ich das eigentlich wollte: auf die Methoden von A
zugreifen zu können, als wären es die Methoden von B
, ohne sie mit einer vollständigen Qualifikation voranstellen zu müssen . Ich habe also, was ich verdient habe. Dies kann jedoch zu einem Problem von außen führen, da es sich um ein Implementierungsdetail von B
handelt, das die Methoden von A
intern verwendet. Es sollte nicht nach außen dringen, aber es tut es. Ich werde versuchen, es irgendwie mit Zugangskontrolle zu beheben, vielleicht wird es irgendwie möglich sein.
Bearbeiten: Ja, dies kann durch Einfügen der folgenden Zeile direkt nach extend A
in B
:
Auf diese Weise kann B
die Methoden von A
intern aufrufen, aber sie sind von außen nicht zugänglich.
Nun, was war falsch mit der ursprünglichen @ sawas Lösung:
Es hat ein drittes Modul verwendet, nur um die Schnittstelle durch es Proxy. Für mich war das eher ein A
oder C
verwenden sollen, und warum solch ein Gerät überhaupt benutzt wird. Es ist nicht offensichtlich, wie es funktioniert, wenn man es nur anschaut. Es bedarf einer gründlichen Analyse, um herauszufinden, was es wirklich macht und warum es so konstruiert ist. Es ist kein sauberes Design.
Andererseits gibt es in meiner Lösung nur zwei Module, wie sie ursprünglich entworfen wurden, und deren Zweck sollte für Benutzer dieser Bibliothek klar sein. Es gibt dieses seltsame extend self
, aber es scheint immer noch ein häufigeres Idiom in Ruby zu sein, als überall Proxy-Module zu verbreiten.
Also danke Jungs für eure Versuche. Nächstes Mal versuchen, weniger arogant zu sein (wenn man sieht, dass jemand eine Frage stellt, ist es nicht immer der Fall, er ist ein Noob) und fixiert auf deine geliebte One True Language (versteh mich nicht falsch, ich mag Ruby Sprache, es ist ziemlich cool und sauber, aber es hat auch einige Nachteile, wie jede Sprache, und es ist besser zu suchen, sie zu lösen, anstatt deine Köpfe zu vergraben und zu tun, dass es überhaupt kein Problem gibt, da es nicht etwas ist, für das die Sprache entworfen wurde.
Ich würde vorschlagen, dass Sie Ihren grundlegenden Prozess überdenken. Dieser Satz ist eine rote Flagge:
Ich habe eine verschachtelte Struktur von Modulen, die nur für Namespacing-Zwecke verwendet werden; kein Mischen in Klassen, die nur für Namespacingzwecke bestimmt sind; kein Mischen in Klassen ...
Dies ist der falsche Weg, um Module zu verwenden, und selbst wenn Sie nicht einverstanden sind, werden Sie das wahrscheinlich mit mehr Erfahrung herausfinden. Ich schlage vor, Ruby Vererbung mehr zu studieren, und die Art, wie Module 'in der Wildnis' verwendet werden. Es gibt viele gute Blogs, Anleitungen und Materialien online, ein Google Klick entfernt ...
Tags und Links ruby namespaces oop module