it-swarm.com.de

Nicht sicher, wann eine abstrakte Eigenschaft verwendet werden soll und wann nicht

Ich bin mir nicht wirklich sicher, was besser aussieht oder wann ich wirklich in abstrakten Klassen und Eigenschaften verwende oder wann nicht abstrakte Eigenschaften verwendet werden. Ich werde versuchen, ein einfaches Beispiel zu machen. Nehmen wir an, ich habe folgendes:

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.

Wenn dies in Ordnung ist, wann würde oder sollte ich dann eine abstrakte Eigenschaft verwenden?

35
miri

Verwenden Sie eine abstrakte Eigenschaft, wenn Sie keine Standardimplementierung haben und von abgeleiteten Klassen implementiert werden müssen.

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

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

Kennzeichnen 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 Mitglied auszublenden (dies ist selten eine gute Idee).

Gewusst wie: Definieren von abstrakten Eigenschaften

Ich finde, dass abstrakte Eigenschaften häufig in einem Design vorkommen, das impliziert, dass sie typspezifische Logik und/oder Nebenwirkungen haben. Sie sagen im Wesentlichen: "Hier ist ein Datenpunkt, den alle Unterklassen haben müssen, aber ich weiß nicht, wie er implementiert werden soll". Jedoch, Eigenschaften, die viel 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.

Sehen:

Ich persönlich finde, dass ich häufig abstrakte Methoden verwende, aber selten abstrakte Eigenschaften.

68
Tim Medora

Ich weiß, was ich will, dass sie es tun, es ist mir egal, wie sie es tun: Schnittstelle.

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

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

Sie können andere Fälle haben, z. eine abstrakte Klasse ohne abstrakte Elemente (Sie können keine Instanz davon haben, aber welche Funktionalität sie bietet, sie bietet sie vollständig an), aber sie sind seltener und kommen normalerweise daher, weil sich eine bestimmte Hierarchie einem gegebenen klar und eindeutig anbietet Problem.

(Übrigens, ich würde nicht von einem Peter als eine Art Mensch sprechen, sondern von jedem Peter als Beispiel eines Menschen, der zufällig als Peter bezeichnet wird. Es ist nicht wirklich gerechtfertigt, Beispielcode auf diese Weise aufzugreifen, aber wenn Sie ' Wenn Sie über diese Art von Gedanken nachdenken, ist dies relevanter als üblich.

27
Jon Hanna

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 möchten, dass sie in der Klasse überschrieben wird, die Ihre Klasse erbt, müssen Sie sie als abstrakte Eigenschaft definieren.

Wenn Sie beispielsweise über eine Tierklasse verfügen, ist es nicht möglich, anhand der Informationen, dass es sich um ein Tier handelt, seine Atmungsaktivität zu bestimmen, aber es ist etwas, das sehr wichtig ist:

public abstract class Animal {

  public abstract bool CanBreathe { get; }

}

Für einen Fisch und einen Hund wäre die Umsetzung anders:

public class Dog : Animal {

   public override bool CanBreathe { get { return !IsUnderWater; } }

}

public class Fish : Animal {

   public override bool CanBreathe { get { return IsUnderWater; } }

}
13
Guffa

Verwenden Sie abstract, wenn alle Unterklassen have die Methode/Eigenschaft implementieren. Wenn für jede Unterklasse keine Notwendigkeit besteht, sie zu implementieren, verwenden Sie sie nicht. 

Wenn in Ihrem Beispiel SecondName nicht für jede Person erforderlich ist, müssen Sie keine abstrakten Eigenschaften in der Basisklasse erstellen. Wenn andererseits jeder Mensch einen zweiten Namen benötigt, dann machen Sie ihn zu einer abstrakten Eigenschaft.

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 korrekt, weil jedes Auto einen Hersteller hat und dem Benutzer mitteilen muss, wer dieser Hersteller ist. 

4
Daniel

Eine abstrakte Eigenschaft würde verwendet werden, wenn die Klasse die Eigenschaft immer verfügbar machen soll, die Implemetation dieser Eigenschaft jedoch nicht festgelegt werden kann. Die ererbende Klasse muss jedoch dazu gezwungen werden.

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

Ihre Implementierung selbst sieht gut aus. Versuchte, ein vernünftiges Beispiel einer abstrakten Eigenschaft für eine Human zu finden, konnte sich aber nichts Vernünftiges vorstellen.

1
Jon Egerton