Wie beschränke ich das Überschreiben in einer Hierarchie?

7

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.

%Vor%

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

    
fletcher 27.07.2010, 14:00
quelle

10 Antworten

10

Anstatt die Beine ein Feld der abstrakten Klasse zu haben, sollten Sie es nur zu einer Eigenschaft machen (entfernen Sie den Setter), und es abstrakt machen.

In Tier

%Vor%

Im Hund

%Vor%     
Mark H 27.07.2010, 14:20
quelle
11

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.

    
mdma 27.07.2010 14:13
quelle
5

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.

    
Dean J 27.07.2010 14:17
quelle
4
%Vor%

?

Ich denke, dann würdest du niemals einen Oktopus als Vierfüßer klassifizieren wollen.

Ich denke, wenn Sie diese Art von Problem haben, müssen Sie die Hierarchie neu anordnen.

    
izb 27.07.2010 14:05
quelle
4

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:

%Vor%

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.

    
Jeff Sternal 27.07.2010 14:26
quelle
1
%Vor%     
Arseny 27.07.2010 14:23
quelle
1

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%

Edit (Lösung mit versiegelt, ein Follow-up auf das )

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%     
Abel 27.07.2010 14:43
quelle
0

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?

    
John M Gant 27.07.2010 14:21
quelle
0

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.

    
SaravananArumugam 27.07.2010 15:11
quelle
0

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.

    
supercat 27.07.2010 16:40
quelle

Tags und Links