Hier einige Code, ich werde Punkte Denken Erbe + Polymorphismus genannt werden, nachdem machen ..
.
public abstract class WeirdPerson() {
public virtual void DoThis() {
// base/default implementation as desired
}
public virtual void DoThat() { // ditto }
public abstract void GoWildAndCrazy;
}
public class WeirdChild : WeirdPerson {
public override void DoThis() { // weird child behavior}
// etc.
}
public class WeirdDad : WeirdPerson {
// override and add methods as needed.
}
public class Version_1
{
public string Name { get; protected set; }
public int Age { get; protected set; }
public WeirdPerson WeirdFamilyMember { get; protected set; }
public MysteriousDad Mysterious { get; protected set; }
public Version_1 (WeirdChild child, string name, int age, MysteriousDad Dad) {
}
}
public class Version_2 : Version_1 {
public Version_2 (WeirdDad dad, string name, int age, MysteriousDad grandfather) : base (dad, name, age, grandfather) {}
}
WeirdPerson
- ein allgemeineres Konzept, das grundlegende Funktionen für alle Untertypen definiert.
- Untertypen erhalten „fixed“ Dinge wie
Name
-Erbe
- Untertypen können
override
Standardverhalten (Methoden) - Polymorphismus
- jetzt haben wir nicht lustig aussehenden Sachen:
public class WeirdDad : WeirdChild
- Konstrukteurs
Version_1
, Version_2
Konstruktoren erzwingen, dass der Client den richtigen WeirdPerson
Untertyp bereitstellt.
- Der Kunde muss uns alle erforderlichen Sachen geben.
- Wir können eingehende Argumente validieren/gegenprüfen.
- Wir brauchen keine keine stinkin
interface
abstract
Klasse uns Standardverhalten (Methoden) und Standardzustand (Eigenschaften)
public
Methoden und Eigenschaften jeder Klasse haben können ein Schnittstelle im allgemeinen Sinne. Wir brauchen nicht (C# -Schlüsselwort) interface
, um dem Prinzip Code zu den Schnittstellen nicht Implementierung
abstract
Methoden zu folgen zwingen Unterklassenimplementierung. gerade. mögen. ein.interface
.
new
- WARNUNG. Das Methodenverbergen trennt die Vererbungskette an diesem Punkt. Wenn wir dann von dieser Klasse erben, erben wir nicht die Methodenimplementierung der ursprünglichen Basisklasse.
- Liskov ist glücklich.
Zusätzliche Refactoring
Machen Sie den Version
Hierarchie parallel die WeirdPerson
Hierarchie
Angenommen, dies in Ihrem Design passt. Ich denke, in einem Jahr wirst du froh sein, dass du es getan hast.
public abstract class Version_X {
// all the original properties here.
// virtual and abstract methods as needed
// LOOK! standard-issue constructor!
protected Version_X (WeirdPerson person, ...) { // common validation, etc. }
}
public class Version_1 : Version_X {
public Version_1(WeirdChild child, ...) : base (child, ...) {}
}
public class Version_2 : Version_X {
public Version_2 (WeirdDad dad, ...) {}
}
Bearbeiten - Motiviert von comment discussion with DVK
Das Mindeste Wissen Prinzip sagt ein Kunde sollte keine internen Details kennen müssen, um eine Klasse zu verwenden. Zu wissen, wie man die richtigen Version
und Weird
verfasst, ist eine Verletzung, könnte man argumentieren.
Lassen Sie uns so tun, dass ein Standardkonstruktor, für Visitor
sagen wir, ist anderswo im Gesamtentwurf notwendig. Dies bedeutet, dass ein Client die Version
/Weird
Zusammensetzung steuern kann.
Abstraktion - lose Kopplung - ist in den abstract
Klassen. Konkrete Klassen müssen notwendigerweise korrekt zusammengesetzt sein, so dass "starke Kopplung" dem Erzeugen konkreter Objekte (den Konstruktorparametern des expliziten Typs) inhärent ist, aber die zugrundeliegende lose Kopplung ermöglicht die gewünschte Flexibilität.
public enum WeirdFamily { Child, Dad, Mother, TheThing }
public static class AdamsFamilyFactory() {
public static Version_X Create (WeirdFamily familyMember) {
switch (familyMember) {
case Dad:
return BuildAdamsDad();
// . . .
}
}
}
public static class MunstersFactory() { // Munsters implementation }
// client code
List<Version_X> AdamsFamily = new List<Version_X>();
Version_X Pugsly = AdamsFamilyFactory.Create(WeirdFamily.Child);
AdamsFamily.Add(Pugsly);
List<Version_X> Munsters= new List<Version_X>();
Version_X Eddie= MunstersFactory.Create(WeirdFamily.Child);
Munsters.Add(Eddie);
DoTheMonsterMash(Munsters);
DoTheMonsterMash(AdamsFamily);
public void DoTheMonsterMash(List<Version_X> someWeirdFamily {
foreach (var member in someWeirdFamily)
member.GoWildAndCrazy();
}
Warum abstrahieren Sie seltsame und mysteriöse Vatereigenschaften, um die abstrakteste Basis, die mit Version 1 möglich ist, zurückzugeben? Die Änderung, die Sie mit v 2 vornehmen möchten, würde den Clientcode beschädigen. Kind und Vater sind beide "Personen", also, haben sie eine Rückkehr Person, machen sie es virtuell, und dann können Sie Ihren seltsamen Getter außer Kraft setzen, ohne Kunden zu bremsen, weil das verrückte Kind auch eine Person ist –
Was Sie suchen, heißt "Verstecken" erhalten wahrscheinlich eine Compilerwarnung, wenn Sie den obigen Code kompilieren, aber Sie verstecken sie explizit, indem Sie die Eigenschaft "new" deklarieren, zB: 'public new WeirdChild Weird {get; einstellen; } 'Beachten Sie jedoch, dass dies bei der Verwendung des' Version_2' -Objekts, das als 'Version_1' deklariert ist, wie' Version_1 untergeordnet = neue Version_2(); verwirrend sein kann. ',' Child.Wierd' wird auf der Basisklasse ausgeführt, nicht auf der abgeleiteten Klasse ein. –
Es tut mir leid, aber Ihre Frage ist nicht klar. Sie möchten nicht die Eigenschaft 'Weird' von der Basisklasse für die Instanz des 'Version_2'-Objekts sehen und diese ausblenden? –