Ist es üblich, eine Unterklasse wie folgt in der Elternklasse zu definieren?
%Vor%Oder ist es sinnvoller, ein Modul zu erstellen, das die Unterklassen enthält?
%Vor%Oder um eine "Basis" -Klasse in einem Modul zu erstellen und die Unterklassen innerhalb desselben Moduls zu definieren?
%Vor%Oder ist es besser, eine Namenskonvention zu erzwingen?
%Vor%Es scheint, dass jede Bibliothek eine andere Namensraum- / Namenskonvention wählt.
Welches ist das beste zu verwenden?
Was sind die Vor- und Nachteile von jedem?
TL; DR : Der üblichste und beste Weg, dies zu tun, ist mit einem Modul, das eine Basisklasse und ihre Unterklassen enthält. Aber lass uns über alles gehen.
Es gibt nicht viele offizielle Quellen dazu; Es ist jedoch der Stil, Module zu verwenden, um Bibliotheken, Code und Klassengruppen zu enthalten.
Vorteile :
Nachteile:
Die Unterklassen in einer Oberklasse zu haben hängt wirklich von der Situation ab. Alle Vorteile dieser Methode werden jedoch auch durch die Modulmethode erreicht. In der Praxis wird dies jedoch nicht getan. Klassen sind hier, um Methoden, Instanzvariablen, Klassenmethoden usw. zu enthalten. Aber Klassen können als letzte Ebene der Verschachtelung betrachtet werden - Sie haben keine Klasse in einer Klasse, es sei denn, es handelt sich um einen sehr spezifischen Umstand.
Der eine Fall, in dem ich dies sinnvoll finden kann, ist ein Fall, in dem Unterklassen nur durch die Oberklasse verwendet werden, zum Beispiel eine Klasse Formatter
, die interne Unterklassen wie XML
, PDF
usw. hat Angenommen, Sie verwenden diese Klassen nur, indem Sie beispielsweise Formatter.new(:xml)
ausführen. Aber wenn wir das tun, sollten die Unterklassen privat und für die Außenwelt sowieso nicht zugänglich sein. Und zu diesem Zeitpunkt ist die Vererbung sehr C ++ y-mäßig und überhaupt nicht Ruby.
Vorteile:
Nachteile:
Diese Methode ist sehr unnatürlich. Es sieht so aus, als ob Element
nichts mit seinen Kindern zu tun hat, oder wenn es anders betrachtet wird, dass Kinder interne Implementierungsdetails sind, die nicht behandelt werden sollen. So oder so sieht es aus wie schäbige, nachlässige Namensgebung und schlechte Code-Struktur-Planung. Wenn ich Code mit diesem Code lesen würde, müsste ich mir den Inhalt des Elements
Moduls anschauen, um zu sehen, dass Element
überhaupt unterklassiert wurde - und das ist nicht die natürlichste Sache.
Vorteile:
include
und den Unterklassen. Sie sind offensichtlich ein Bündel von Funktionen. Nachteile:
Element
zu nennen, die sehr mehrdeutig sind. Dies ist der beste Ansatz. Es macht die Klassen zu einem ordentlichen Bündel, während es immer noch eine offensichtliche Assoziation und ein offensichtliches "Hier, benutze meine Base
-Klasse" (im Gegensatz zu der Unterklassen-in-Klassen-Strategie) zeigt. Dies ist auch sehr hilfreich für das Metaprogrammieren, bei dem alles in einem Modul entscheidend ist, damit die Dinge funktionieren. Schließlich funktioniert das gut mit Konstrukten wie Div
, autoload
, require_relative
usw. Diese zeigen, dass die Sprache so entworfen wurde, um verwendet zu werden.
Vorteile:
include
oder Div
, indem sie in Para
und DivElement
. Nachteile:
Dies ist eine sehr , SEHR schlechte Lösung. Es kodiert für schlampigen C-Code mit wenig Organisation und wenig Sinn. Diese Arten von Namenskonventionen sollten nur in Sprachen verwendet werden, in denen es keine bessere Lösung gibt, und Ruby hat viele bessere Lösungen. Selbst das Definieren aller Klassen in einem Array ist besser als eine Namenskonvention.
Hinweis: Wenn Sie das wirklich möchten, können Sie eine Namenskonvention für kurze Namen wie ParaElement
oder Div
definieren, solange Sie sie in einem Modul behalten, so dass Para
lautet. Dies verstößt jedoch gegen DRY, und ich würde es nicht vorschlagen.
Sie haben also wirklich zwei Möglichkeiten.Stellen Sie einfach alles in ein Modul:
%Vor%Oder fügen Sie alles in ein Modul mit einer Namenskonvention ein:
%Vor%Ich sptere ersteres für die Klarheit, die Verwendung von Standardmethoden und Metaprogrammierungsgründen.
Dies ist ein Problem, mit dem ich viele Male konfrontiert war - Sie haben einige gemeinsame Funktionen und ein paar verschiedene Implementierungsklassen, die es verwenden - die gemeinsame Funktionalität und der Namensraum für die Implementierungsklassen haben denselben Namen.
>Ich hatte nie ein Problem, eine Unterklasse wie in Ihrem ersten Beispiel unter der Elternklasse zu definieren - außer , weil es manchmal andere Entwickler in meinem Team verwirrt hat. Je nachdem, mit wem Sie arbeiten und was ihre Präferenzen sind, glaube ich nicht, dass es ein Problem mit diesem Ansatz gibt.
Ich würde immer noch den zweiten Ansatz mit einem anderen Namen für den Namensraum bevorzugen, wenn es einen Namen gibt, der Sinn ergibt. Wenn nicht, würde ich den ersten Ansatz verwenden.
Ich würde es vermeiden, Namen wie Base
zu verwenden, da diese Art von generischem Namen meiner Meinung nach dazu anregt, nur altes Zeug hineinzuwerfen, während ein Name, der beschreibt, was die Klasse macht, Sie (hoffentlich) zum Nachdenken anregt Mal fügst du eine Methode hinzu, wenn sie wirklich dorthin gehört.
Und ich bin wirklich kein Fan von zusammengesetzten Namen wie in Ihrem Namenskonvention Beispiel, das ich mir mit einer Art von vage Gefühl, dass es wie Datenbank-Normalisierung ist rechtfertigen - jedes Feld (oder Klassenname) sollte nur ein Stück enthalten von Informationen.
Jedenfalls hoffe ich, dass dir das weiterhilft. Ich kann nicht wirklich aus anderen Quellen als meiner eigenen Erfahrung schöpfen (es ist für dich, zu entscheiden, ob du glaubst, dass das "glaubwürdig" ist), da ich glaube, dass es keine absolute Antwort auf diese Frage gibt. Es ist zu einem großen Teil subjektiv.
Namensraum und Vererbung dienen verschiedenen Zwecken. Verwenden Sie den Namensraum, um ein Modul in einem anderen zu kapseln. Verwenden Sie Vererbung, um ein Modul zu definieren, das die Methoden / Variablen / Konstanten eines anderen standardmäßig verwendet.
Es könnte im Prinzip passieren, dass Sie möchten, dass ein Modul innerhalb des Namensraums von demselben Modul ist und von demselben Modul erbt, aber das hängt von Ihrem Anwendungsfall ab. Ohne über einen bestimmten Anwendungsfall zu diskutieren, kann nicht entschieden werden, welcher der von Ihnen vorgeschlagenen Wege der beste ist.
Tags und Links ruby