it-swarm.com.de

Wann soll ein gemeinsames Feld in eine Basisklasse verschoben werden?

Ich habe derzeit zwei abgeleitete Klassen, A und B, die beide ein gemeinsames Feld haben, und ich versuche festzustellen, ob es in die Basisklasse aufgenommen werden soll.

Es wird nie von der Basisklasse referenziert, und wenn irgendwann irgendwann eine andere Klasse abgeleitet wird, C, die keinen _field1 Hat, dann würde das Prinzipal von nicht "am wenigsten privilegiert" (oder etwas) verletzt werden, wenn es war?

public abstract class Base
{
    // Should _field1 be brought up to Base?
    //protected int Field1 { get; set; }
}

public class A : Base
{
    private int _field1;
}

public class B : Base
{
    private int _field1;
}

public class C : Base
{
    // Doesn't have/reference _field1
}
16
samis

Es hängt alles von dem genauen Problem ab, das Sie lösen möchten.

Stellen Sie sich ein konkretes Beispiel vor: Ihre abstrakte Basisklasse ist Vehicle und Sie haben derzeit die konkreten Implementierungen Bicycle und Car. Sie erwägen, numberOfWheels von Bicycle und Car zum Fahrzeug zu verschieben. Solltest du das tun? Nein! Weil nicht alle Fahrzeuge Räder haben. Sie können bereits erkennen, dass wenn Sie versuchen, eine Boat -Klasse hinzuzufügen, diese unterbrochen wird.

Wenn Ihre abstrakte Basisklasse WheeledVehicle war, ist es logisch, die Mitgliedsvariable numberOfWheels dort zu haben.

Sie müssen dieselbe Logik auf Ihr Problem anwenden, da es sich, wie Sie sehen können, nicht um eine einfache Ja- oder Nein-Antwort handelt.

34
Pete

Logischerweise gibt es neben dem Platzieren des in Unterklassen replizierten Felds im Vergleich zu gemeinsamen Feldern in der Basisklasse eine dritte Option: eine neue Unterklasse in die Hierarchie einzuführen, die die gemeinsamen Eigenschaften zwischen beiden aufweist. @Pete weist darauf hin, ohne vollständig dorthin zu gehen.

Am Beispiel von @ Pete würden wir eine (möglicherweise abstrakte) Unterklasse für Radfahrzeuge einführen, die von der ursprünglichen Basisklasse abstammt - während die beiden Unterklassen davon abstammen. Somit ist die ursprüngliche Basisklasse nicht mit Rädern verschmutzt, die Gemeinsamkeit der Räder ist jedoch DRY (wird bei Unterklassen mit Rädern nicht wiederholt).

Dies kann für Ihre Zwecke natürlich übertrieben sein, wird jedoch vom Klassenhierarchiemechanismus unterstützt.

13
Erik Eidt

Ich werde hier Devil's Advocate spielen.

Im Moment solltest du nichts tun.

Ist es trocken? Nein. Aber es ist besser, ein wenig zu duplizieren als eine vorzeitige Abstraktion, aus der Sie später nicht einfach herauskommen können. Der Refactor zum Verschieben einer Eigenschaft in eine gemeinsame Basisklasse ist einfach. Den anderen Weg zu gehen ist nicht. Warten wir es ab.

Wenn ich diese Art von Entscheidung treffe, neige ich dazu, eine "Regel von 3" zu verwenden: Sobald ich dasselbe in z. an drei verschiedenen Stellen, und erst dann denke ich darüber nach, es die Kette hinauf zu bewegen. N.B. Du bist erst bei 2.

9
Jared Smith

Im Allgemeinen würde ich es in die Basisklasse verschieben. Ich glaube nicht, dass es ein objektives Ja/Nein gibt, weil es hier einen Kompromiss gibt - ungenutzte Felder zu tragen oder Komplexität zu reduzieren.

Normalerweise bevorzuge ich 'schwere' Basisklassen, die alles enthalten, was geteilt werden könnte. Dies vereinfacht die Serialisierung in Dateien, da Sie nicht in jeder abgeleiteten Klasse nachfolgende Serialisierungsmethoden benötigen. Aber wenn Sie dieses oder ein ähnliches Problem nicht haben oder vielleicht alles tun müssen, um die Speichernutzung zu reduzieren, sollte es in Ordnung sein, nur die Felder dort zu belassen, wo Sie sie benötigen.

Eine 'Zwischenklasse', die die allgemeinen Felder einführt, ist in Ordnung, wenn Sie eine sehr begrenzte Anzahl von Feldern haben. Beachten Sie jedoch, dass der Ansatz die Komplexität erheblich erhöhen kann, wenn Sie Dutzende von Feldern in unterschiedlichen Kombinationen verwenden, was dazu führt, dass viele Zwischenklassen jeweils einen bestimmten Satz von Feldern einführen. Das kann zu einem Wartungsproblem werden.

2
GrandmasterB