Ich habe eine abstrakte Basisklasse und möchte ein Feld oder eine Eigenschaft deklarieren, die in jeder Klasse, die von dieser übergeordneten Klasse erbt, einen anderen Wert hat.
Ich möchte es in der Basisklasse definieren, damit ich es in einer Basisklassenmethode referenzieren kann - zum Beispiel, wenn ToString überschrieben wird, um zu sagen, dass dieses Objekt vom Typ Eigenschaft / Feld ist . Ich habe drei Möglichkeiten, wie ich das sehen kann, aber ich habe mich gefragt - was ist die beste oder akzeptierte Art, dies zu tun? Neuling Frage, sorry.
Option 1:
Verwenden Sie eine abstrakte Eigenschaft und überschreiben Sie sie für die geerbten Klassen. Dies profitiert von der Durchsetzung (Sie müssen es überschreiben) und es ist sauber. Es fühlt sich jedoch etwas falsch an, einen Hardcode-Wert zurückzugeben, anstatt ein Feld zu kapseln, und es sind ein paar Codezeilen statt nur. Ich muss auch einen Körper für "set" deklarieren, aber das ist weniger wichtig (und es gibt wahrscheinlich einen Weg, das zu vermeiden, was mir nicht bekannt ist).
abstract class Father
{
abstract public int MyInt { get; set;}
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
set { }
}
}
Option 2
Ich kann ein öffentliches Feld (oder ein geschütztes Feld) deklarieren und es in der geerbten Klasse explizit überschreiben. Das folgende Beispiel gibt mir eine Warnung, "neu" zu verwenden, und ich kann das wahrscheinlich tun, aber es fühlt sich falsch an und bricht den Polymorphismus, worum es ging. Scheint keine gute Idee zu sein ...
abstract class Mother
{
public int MyInt = 0;
}
class Daughter : Mother
{
public int MyInt = 1;
}
Option 3
Ich kann ein geschütztes Feld verwenden und den Wert im Konstruktor festlegen. Dies scheint ziemlich ordentlich zu sein, aber ich muss sicherstellen, dass der Konstruktor dies immer festlegt. Bei mehreren überladenen Konstruktoren besteht immer die Möglichkeit, dass ein Codepfad den Wert nicht festlegt.
abstract class Aunt
{
protected int MyInt;
}
class Niece : Aunt
{
public Niece()
{
MyInt = 1;
}
}
Es ist eine theoretische Frage, und ich denke, die Antwort muss Option 1 sein, da dies die einzig sichere Option ist, aber ich habe gerade C # in den Griff bekommen und wollte dies Leuten mit mehr Erfahrung stellen.
quelle
Antworten:
Von den drei Lösungen nur 1 Option ist polymorph .
Felder selbst können nicht überschrieben werden. Genau aus diesem Grund gibt Option 2 die neue Keyword-Warnung zurück.
Die Lösung für die Warnung besteht nicht darin, das Schlüsselwort "new" anzuhängen, sondern Option 1 zu implementieren.
Wenn Ihr Feld polymorph sein soll, müssen Sie es in eine Eigenschaft einschließen.
Option 3 ist in Ordnung, wenn Sie kein polymorphes Verhalten benötigen. Beachten Sie jedoch, dass die abgeleitete Klasse beim Zugriff auf die Eigenschaft MyInt zur Laufzeit keine Kontrolle über den zurückgegebenen Wert hat. Die Basisklasse selbst kann diesen Wert zurückgeben.
So könnte eine wirklich polymorphe Implementierung Ihrer Eigenschaft aussehen, sodass die abgeleiteten Klassen die Kontrolle behalten .
quelle
Option 2 ist kein Starter - Sie können Felder nicht überschreiben , sondern nur ausblenden .
Persönlich würde ich mich jedes Mal für Option 1 entscheiden. Ich versuche, Felder jederzeit privat zu halten. Das ist natürlich der Fall, wenn Sie wirklich in der Lage sein müssen, die Eigenschaft überhaupt zu überschreiben. Eine andere Option besteht darin, eine schreibgeschützte Eigenschaft in der Basisklasse zu haben, die über einen Konstruktorparameter festgelegt wird:
Dies ist wahrscheinlich der am besten geeignete Ansatz, wenn sich der Wert während der Lebensdauer der Instanz nicht ändert.
quelle
Option 2 ist eine schlechte Idee. Es wird zu etwas führen, das als Schatten bezeichnet wird. Grundsätzlich haben Sie zwei verschiedene "MyInt" -Mitglieder, eines bei der Mutter und das andere bei der Tochter. Das Problem dabei ist, dass in der Mutter implementierte Methoden auf das "MyInt" der Mutter verweisen, während in der Tochter implementierte Methoden auf das "MyInt" der Tochter verweisen. Dies kann zu ernsthaften Lesbarkeitsproblemen und später zu Verwirrung führen.
Persönlich denke ich, dass die beste Option 3 ist; weil es einen klaren zentralisierten Wert bietet und von Kindern intern referenziert werden kann, ohne dass sie ihre eigenen Felder definieren müssen - was das Problem bei Option 1 ist.
quelle
Du könntest das tun
Mit virtual können Sie einer Eigenschaft einen Body zuweisen, der etwas tut, und Unterklassen können ihn dennoch überschreiben.
quelle
Sie könnten so etwas definieren:
Durch Festlegen des Werts als schreibgeschützt wird sichergestellt, dass der Wert für diese Klasse während der Lebensdauer des Objekts unverändert bleibt.
Ich nehme an, die nächste Frage ist: Warum brauchst du sie?
quelle
Wenn Sie eine Klasse erstellen und möchten, dass es einen Basiswert für die Eigenschaft gibt, verwenden Sie das
virtual
Schlüsselwort in der Basisklasse. Auf diese Weise können Sie die Eigenschaft optional überschreiben.Verwenden Sie Ihr Beispiel oben:
In einem Programm:
quelle
Ich würde mich für Option 3 entscheiden, habe aber eine abstrakte setMyInt-Methode, die von Unterklassen implementiert werden muss. Auf diese Weise haben Sie nicht das Problem, dass eine abgeleitete Klasse vergisst, sie im Konstruktor festzulegen.
Übrigens mit Option eins, wenn Sie set nicht angeben; In Ihrer abstrakten Basisklasseneigenschaft muss die abgeleitete Klasse sie nicht implementieren.
quelle
Sie können mit Option 3 fortfahren. Wenn Sie Ihre abstrakte Basisklasse so ändern, dass der Eigenschaftswert im Konstruktor erforderlich ist, werden Sie keine Pfade verpassen. Ich würde diese Option wirklich in Betracht ziehen.
Natürlich haben Sie dann immer noch die Möglichkeit, das Feld privat zu machen und dann je nach Bedarf einen geschützten oder öffentlichen Güter zu entlarven.
quelle
Ich war das...
Auf diese Weise können Sie weiterhin Felder verwenden.
quelle
Die Beispielimplementierung, wenn Sie eine abstrakte Klasse mit Implementierung haben möchten. Unterklassen müssen:
In diesem Fall sollten die für die Implementierung erforderlichen Eigenschaften nur für die abstrakte Klasse und ihre eigene Unterklasse zur Verfügung stehen.
quelle