Dies ist ein Beispiel, ich bin nur neugierig, wie es erreicht werden würde.
Ich möchte nur Unterklassen von Animal
in die Lage versetzen, die Anzahl der Beine, die sie haben, zu setzen, aber ich möchte immer noch, dass sie ihre eigene Farbe einstellen können. Daher möchte ich Klassen weiter unten in der Hierarchie einschränken, um diese Eigenschaft Legs
zu ändern.
Zum Beispiel möchte ich diese Art von Unterklasse eliminieren:
%Vor%Wie würde das erreicht?
Ich bin mir bewusst, dass ich das Überschreiben in einer Unterklasse beenden konnte, indem ich die Implementierung einer Funktion in der Elternklasse versiegelte. Ich habe das mit der Eigenschaft Legs
versucht, aber ich konnte es nicht zum Laufen bringen.
Danke
Teilweise verstößt dies gegen OO-Prinzipien. Deine Superklasse Animal stellt einen Vertrag zur Verfügung, der das Set / Get für Legs beinhaltet. Sie möchten dann, dass eine Unterklasse diese Schnittstelle so einschränken kann, dass gesetzte Legs nicht zulässig sind. Da die Unterklasse eine "is-a" -Beziehung bereitstellt, geht die Einschränkung der Schnittstelle dagegen, was bedeuten würde, dass Unterklassen keine wahren Subtypen wären, da die gesetzten Legs-Methoden nicht vorhanden sind.
Ich würde den Setter für die Legs-Eigenschaft aus Animal entfernen, da dies ein Implementierungsdetail ist. Stattdessen einfach einen abstrakten Getter haben. Unterklassen können dann entscheiden, wie sie dies am besten implementieren, indem sie entweder einen fest codierten Wert zurückgeben oder ein Feld zum Speichern des Werts verwenden.
In Java würden Sie die Getter- und Setter-Methoden endgültig machen, damit sie nicht überschrieben werden können. In C # glaube ich, dass das gewünschte Keyword "versiegelt" ist. Sie versiegeln die Methode, aber nicht die gesamte Unterklasse.
Sie würden die Variable selbst als privat definieren, also müssten Unterklassen einen Getter / Setter verwenden, um auf die Variable zuzugreifen.
Ihre Frage besagt, dass diese Klassen ideale Tiere und nicht tatsächliche Tierfälle darstellen - schließlich haben einzelne Tiere eine variable Anzahl von Beinen.
Wenn das der Fall ist, wollen Sie nicht wirklich einen Setter für Legs
an erster Stelle. Der Setter ist ein Konstruktionsfehler, da die Semantik falsch ist: kein Aufrufer, einschließlich Unterklassen, sollte in der Lage sein, die Anzahl der Zweige zu einem beliebigen Zeitpunkt einzustellen.
Fordern Sie stattdessen die Anzahl der Zweige in einem geschützten Animal
-Konstruktor (und wahrscheinlich auch die Farbe) an:
Wenn Sie zu einem späteren Zeitpunkt entscheiden, dass Dog
-Unterklassen dies alles einstellen müssen, können Sie einfach einen neuen Konstruktor hinzufügen, der dies zulässt.
Im Grunde genommen kann dies nicht mit C # geschehen, wie von mehreren Posts in diesem Thread gesagt wurde. Es wurde argumentiert, dass dies keine ordnungsgemäße OO ist, aber ich stimme nicht zu. Wenn Sie es zur Hand haben, finden Sie auf der Seite 464+ von OOSC weitere Informationen. Der hier verwendete Begriff ist Invariante Vererbung . Das angegebene Beispiel ist ein Rectangle
(immer vier Seiten) und erbt von Polygon
(jede Menge Seiten größer als 2).
Die Regel ist einfach, Zitat:
Die invariante Eigenschaft einer Klasse ist der boolesche
and
der Assertions in ihr erscheint Invariante Klausel und der invarianten Eigenschaften seiner Eltern, falls vorhanden.
Bertrand Meyer verwendet Design By Contract. In geringerem Umfang ist dies auch für C # verfügbar. Mit .NET 4.0 ist es ist über Spec # verfügbar geworden.
Über das Argument, dass dies kein richtiges OO ist: das Argument ist korrekt (Vererbung in der Kette verhindert den Vertrag), aber ohne die Vererbung zu verhindern, aber durch Verwendung invarianter Klauseln Einschränkungen für die Werte hinzuzufügen Das OO-Paradigma wird gespeichert und die Vererbungskette bleibt erhalten. Etwas wie das:
%Vor%
Wie in einem der Threads verlangt, ist hier ein kleines Beispiel, das das weitere Erben eines Mitglieds abschirmt (etwas, das hier als Verletzung von OO angesehen wird, während die Sprachdesigner klar verstanden, dass es das nicht ist):
%Vor%Sie könnten auch darüber nachdenken, was passieren würde, wenn jemand eine Variable oder einen Parameter erstellt oder Animal eingibt und dann versucht, seine Legs-Eigenschaft festzulegen. Würden Sie eine bestimmte Ausnahme auslösen, wenn es eine der Unterklassen wäre, die es nicht erlaubt, ihre Zweige zu setzen?
Zum Beispiel.
%Vor% Wenn Animal.Legs
ein öffentliches Eigentum ist, habe ich allen Grund zu der Annahme, dass das funktionieren wird. Was aber, wenn der Anrufer einen Hund eingibt?
Fügen Sie in den Unterklassen von Animal die Eigenschaft set accessor der Leg-Eigenschaft als privat ein. [Hinweis: In der Tierklasse muss Leg-Eigenschaft virtuell gemacht werden.]
%Vor%Dies wird verhindern, dass eine Ableitung von Dog die Leg-Eigenschaft setzt.
Der richtige Ansatz besteht darin, die Anzahl der Zweige zu einer abstrakten schreibgeschützten Eigenschaft zu machen. Um Hunde zu erstellen, deren Beinzählung nicht überschrieben werden kann, muss eine Klasse der mittleren Ebene erstellt werden, die eine Implementierung für die NumberOfLegs-Eigenschaft definiert und anschließend die Dog-Klasse mit einer öffentlichen NumberOfLegs-Funktion definiert, die die Basis schattiert Klasseneigentum. Jede Bemühung, die Anzahl der Zweige zu überschreiben, würde auf die Schatteneigenschaft gerichtet sein, so dass das Original nicht mehr überschrieben werden könnte.
Es wäre schöner, wenn man für dieselbe Eigenschaft im selben Bereich verschiedene Overrides und Shadows-Implementationen definieren könnte (wobei die Overrides nur verwendet werden, wenn auf die Eigenschaft in der Basisklasse zugegriffen wird), aber ich weiß es nicht um das zu tun.
Tags und Links .net c# inheritance override