2012-09-03 11 views
29

Ich bin nicht wirklich sicher, was besser aussieht oder wann verwende ich wirklich in abstrakten Klassen und Eigenschaften oder wann nicht abstrakte Eigenschaften zu verwenden. Ich werde versuchen, ein einfaches Beispiel zu geben. Nehmen wir an, ich habe folgendes:Nicht sicher, wann eine abstrakte Eigenschaft zu verwenden ist und wann nicht

abstract class Human 
{ 
    public GenderType Gender { get; set; } 
    public string Name { get; set; } 
    public Date Born { get; set; } 
    public bool IsNerd { get; set; } 

    abstract public void Speak(); 
    abstract public void Sleep(); 
    abstract public void AnoyingPeopleOnStackOverflow(); 
    //... so on 
} 

class Peter : Human 
{ 
    //Peter is special, he got a second name 
    //But thats all, everything else is the same as like on other humans 
    public string SecondName { get; set; } 

    //...override abstract stuff 
} 

Ist das in Ordnung? Wie ich verstanden habe, muss ich keine abstrakte Eigenschaft verwenden, wenn ich sie nicht überschreiben möchte. Und in dieser Situation wäre es in Ordnung, nur die Methoden wie Speak, Sleep und so weiter sollten abstrakt sein.

Nun, wenn das in Ordnung ist, wann oder sollte ich eine abstrakte Eigenschaft verwenden?

+1

"Wann würde oder sollte ich eine abstrakte Eigenschaft verwenden" --- Wenn Sie behaupten wollen, dass die Kindklasse eine spezifische Methodenimplementierung bereitstellen muss – zerkms

+1

1) Wenn dies Java wäre, gäbe es wahrscheinlich kein Problem. Sie würden wahrscheinlich nur eine "Schnittstelle" verwenden. Das ist im Wesentlichen das, was du hier in C# tust, oder?2) Mein persönliches Gefühl ist, dass es, wenn es Teil des "Vertrags" sein muss, angemessen ist, es in Ihrer abstrakten Klasse zu deklarieren. Mit anderen Worten, ich denke, was Sie getan haben, ist vollkommen in Ordnung. IMHO ... – paulsm4

+1

@ paulsm4 können Sie das auch mit C# tun. –

Antwort

56

Verwenden Sie eine abstrakte Eigenschaft, wenn Sie keine Standardimplementierung haben und wenn abgeleitete Klassen sie implementieren müssen.

Verwenden Sie eine virtuelle Eigenschaft, wenn Sie eine Implementierung in der Basisklasse haben, aber das Überschreiben zulassen möchten.

Verwenden Sie das Schlüsselwort override, um ein Element zu überschreiben. Markieren Sie das Mitglied als sealed override, wenn es nicht erneut überschrieben werden soll.

Markieren Sie die Eigenschaft nicht als abstract oder virtual, wenn Sie nicht möchten, dass sie überschrieben wird.

Verwenden Sie das Schlüsselwort new, um ein nicht abstraktes, nicht virtuelles Element auszublenden (dies ist selten eine gute Idee).

How to: Define Abstract Properties

Ich finde, dass abstrakte Eigenschaften oft in einem Design auftreten, was bedeutet, dass sie typspezifische Logik und/oder Nebenwirkungen haben. Sie sagen im Grunde: "Hier ist ein Datenpunkt, den alle Unterklassen haben müssen, aber ich weiß nicht, wie ich es implementieren soll". Jedoch, Eigenschaften, die eine große Menge an Logik enthalten und/oder Nebenwirkungen verursachen, sind möglicherweise nicht wünschenswert. Dies ist eine wichtige Überlegung, obwohl es keinen festen richtigen/falschen Weg gibt, dies zu tun.

Siehe:

Persönlich finde ich, dass ich häufig abstrakte Methoden verwenden, aber abstrakte Eigenschaften selten.

4

Verwenden Sie die Zusammenfassung, wenn alle Unterklassen haben, um die Methode/property zu implementieren. Wenn es nicht erforderlich ist, dass jede Unterklasse es implementiert, dann verwenden Sie es nicht.

Wenn für Ihr Beispiel SecondName nicht für jede Person erforderlich ist, müssen Sie in der Basisklasse keine abstrakte Eigenschaft erstellen. Wenn andererseits jede Person einen zweiten Namen braucht, dann sollte sie eine abstrakte Eigenschaft sein.

Beispiel für die korrekte Verwendung einer abstrakten Eigenschaft:

public class Car 
{ 
    public abstract string Manufacturer { get; } 
} 

public class Odyssey : Car 
{ 
    public override string Manufacturer 
    { 
     get 
     { 
      return "Honda"; 
     } 
    } 
} 

public class Camry : Car 
{ 
    public override string Manufacturer 
    { 
     get 
     { 
      return "Toyota"; 
     } 
    } 
} 

Maker abstrakt zu machen ist richtig, weil jedes Auto einen Hersteller hat und muss in der Lage sein, dem Benutzer zu sagen, wer die Hersteller sind.

1

Eine abstrakte Eigenschaft wird verwendet, wenn die Klasse die Eigenschaft immer verfügbar machen soll, die Implementierung dieser Eigenschaft jedoch nicht festgeschrieben werden kann - die erbende Klasse bleibt dabei/erzwingen.

Es gibt ein Beispiel here, in dem die abstrakte Klasse Shape heißt und eine abstrakte Area-Eigenschaft verfügbar macht. Sie können die Eigenschaft Area in der Basisklasse nicht implementieren, da sich die Formel für den Bereich für jeden Formtyp ändert. Alle Formen haben einen bestimmten Bereich, daher sollten alle Formen die Eigenschaft freilegen.

Ihre Implementierung selbst sieht gut aus. Ich habe versucht, an ein vernünftiges Beispiel für eine abstrakte Eigenschaft für eine Human zu denken, konnte aber nichts vernünftiges denken.

11

Abstrakte Mitglieder sind einfach virtuelle Mitglieder, die Sie überschreiben müssen. Sie verwenden dies für etwas, das implementiert werden muss, aber nicht in der Basisklasse implementiert werden kann.

Wenn Sie eine virtuelle Eigenschaft erstellen möchten und diese in der Klasse überschrieben werden soll, die Ihre Klasse erbt, dann würden Sie sie als abstrakte Eigenschaft definieren.

Wenn Sie zum Beispiel ein Tier Klasse, seine Fähigkeit, möglich sein würde zu atmen nicht nur aus den Informationen detemine, dass es ein Tier ist, aber es ist etwas, das ziemlich entscheidend ist:

public abstract class Animal { 

    public abstract bool CanBreathe { get; } 

} 

Für einen Fisch und ein Hund würde die Implementierung anders sein:

26

Ich weiß, was ich sie tun soll, ist mir egal, wie sie es tun: Interface.

Ich weiß, was ich will, dass sie tun, ist mir egal, wie sie etwas davon tun, aber ich habe feste Vorstellungen darüber, wie sie (oder zumindest die meisten von ihnen) andere Bits machen: Abstrakte Klasse .

Ich weiß, was ich will, und wie die meisten von ihnen es tun: Konkrete Klasse mit virtuellen Mitgliedern.

Sie können andere Fälle wie z.B. eine abstrakte Klasse ohne abstrakte Mitglieder (man kann keine Instanz von einer haben, aber welche Funktionalität bietet sie an, bietet sie vollständig an), aber sie sind seltener und entstehen normalerweise, weil sich eine bestimmte Hierarchie sauber und unverhohlen einer gegebenen anbietet Problem.

(Übrigens würde ich nicht einen Peter als eine Art von Mensch, sondern von jedem Peter als eine Instanz von Menschen, der zufällig Peter genannt wird. Es ist nicht wirklich fair, Beispielcode auf diese Weise zu wählen, aber wenn Sie über diese Art von Problem nachdenken, ist es relevanter als üblich).

+3

+1 - stimme zu, "Peter" sollte eine Instanz einer Unterklasse von "Human" sein, z. 'HumansWithTwoNames' –

+2

@TimMedora Ja, und wir denken alle an schlechte Namen, wenn wir Beispielcode zusammenstellen, und das ist normalerweise egal, aber das ist eine Frage, bei der es mehr zählt als die meisten anderen. –

Verwandte Themen