522 Stimmen

Wann sollte man eine Schnittstelle anstelle einer abstrakten Klasse verwenden und umgekehrt?

Dies könnte eine allgemeine OOP-Frage sein. Ich wollte einen generischen Vergleich zwischen einer Schnittstelle und einer abstrakten Klasse auf der Grundlage ihrer Verwendung anstellen.

Wann würde man eine Schnittstelle und wann eine abstrakte Klasse verwenden wollen? ?

10voto

Ich habe einen Artikel darüber geschrieben, wann man eine abstrakte Klasse und wann man eine Schnittstelle verwenden sollte. Es gibt viel mehr Unterschiede zwischen ihnen als nur "eine IST... und eine KANN...". Für mich sind das Antworten aus der Konserve. Ich nenne ein paar Gründe, wann man eine von beiden verwenden sollte. Ich hoffe, es hilft.

http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/

9voto

Domn Werner Punkte 472

Ich denke, die prägnanteste Formulierung ist die folgende:

Gemeinsame Eigenschaften => abstrakte Klasse.
Gemeinsame Funktionalität => Schnittstelle.

Und um es weniger lapidar zu formulieren...

Beispiel für eine abstrakte Klasse:

public abstract class BaseAnimal
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }
}

public class Dog : BaseAnimal
{
    public Dog() : base(4) { }
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }
}

Da Tiere eine gemeinsame Eigenschaft haben - in diesem Fall die Anzahl der Beine - ist es sinnvoll, eine abstrakte Klasse zu erstellen, die diese gemeinsame Eigenschaft enthält. Dies ermöglicht es uns auch, gemeinsamen Code zu schreiben, der mit dieser Eigenschaft arbeitet. Zum Beispiel:

public static int CountAllLegs(List<BaseAnimal> animals)
{
    int legCount = 0;
    foreach (BaseAnimal animal in animals)
    {
        legCount += animal.NumberOfLegs;
    }
    return legCount;
}

Beispiel für eine Schnittstelle:

public interface IMakeSound
{
    void MakeSound();
}

public class Car : IMakeSound
{
    public void MakeSound() => Console.WriteLine("Vroom!");
}

public class Vuvuzela : IMakeSound
{
    public void MakeSound() => Console.WriteLine("VZZZZZZZZZZZZZ!");        
}

Beachten Sie hier, dass Vuvuzelas und Autos völlig unterschiedliche Dinge sind, aber eine gemeinsame Funktion haben: ein Geräusch zu machen. Daher ist eine Schnittstelle hier sinnvoll. Außerdem ermöglicht es Programmierern, Dinge, die Geräusche machen, unter einer gemeinsamen Schnittstelle zusammenzufassen -- IMakeSound in diesem Fall. Mit diesem Entwurf könnten Sie den folgenden Code schreiben:

List<IMakeSound> soundMakers = new List<ImakeSound>();
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Vuvuzela());

foreach (IMakeSound soundMaker in soundMakers)
{
    soundMaker.MakeSound();
}

Können Sie sagen, was dabei herauskommen würde?

Und schließlich können Sie beides kombinieren.

Kombiniertes Beispiel:

public interface IMakeSound
{
    void MakeSound();
}

public abstract class BaseAnimal : IMakeSound
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }

    public abstract void MakeSound();
}

public class Cat : BaseAnimal
{
    public Cat() : base(4) { }

    public override void MakeSound() => Console.WriteLine("Meow!");
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }

    public override void MakeSound() => Console.WriteLine("Hello, world!");
}

Hier benötigen wir alle BaseAnimal s ein Geräusch machen, aber wir kennen seine Umsetzung noch nicht. In einem solchen Fall können wir die Schnittstellenimplementierung abstrahieren und ihre Implementierung an ihre Unterklassen delegieren.

Ein letzter Punkt: Erinnern Sie sich daran, dass wir im Beispiel der abstrakten Klasse die gemeinsamen Eigenschaften verschiedener Objekte bearbeiten konnten und im Beispiel der Schnittstelle die gemeinsame Funktionalität verschiedener Objekte aufrufen konnten? In diesem letzten Beispiel konnten wir beides tun.

6voto

Erwägen Sie die Verwendung von abstrakte Klassen wenn eine dieser Aussagen auf Ihre Situation zutrifft:

  1. Sie möchten den Code für mehrere eng miteinander verbundene Klassen gemeinsam nutzen.
  2. Sie erwarten, dass Klassen, die Ihre abstrakte Klasse erweitern, viele gemeinsame Methoden oder Felder haben oder andere Zugriffsmodifikatoren als public (wie protected und private) benötigen.
  3. Sie wollen nicht-statische oder nicht-finale Felder deklarieren. Dadurch können Sie Methoden definieren, die auf den Zustand des Objekts, zu dem sie gehören, zugreifen und ihn ändern können.

Erwägen Sie die Verwendung von Schnittstellen wenn eine dieser Aussagen auf Ihre Situation zutrifft:

  1. Sie erwarten, dass nicht verwandte Klassen Ihre Schnittstelle implementieren würden. Die Schnittstellen Comparable und Cloneable werden zum Beispiel von vielen nicht verwandten Klassen implementiert.
  2. Sie möchten das Verhalten eines bestimmten Datentyps festlegen, sich aber nicht darum kümmern, wer dieses Verhalten implementiert.
  3. Sie möchten die Vorteile von Mehrfachvererbungen nutzen.

Quelle

2voto

Nick Fortescue Punkte 41671

Die Antworten sind von Sprache zu Sprache unterschiedlich. In Java zum Beispiel kann eine Klasse mehrere Schnittstellen implementieren (von ihnen erben), aber nur von einer abstrakten Klasse erben. Schnittstellen geben Ihnen also mehr Flexibilität. In C++ ist dies jedoch nicht der Fall.

2voto

La VloZ Merrill Punkte 173

Ich würde mich in vielen Fällen für die Schnittstellen entscheiden. Aber in manchen Fällen ziehe ich abstrakte Klassen vor.

Klassen in OO beziehen sich im Allgemeinen auf die Implementierung. Ich verwende abstrakte Klassen, wenn ich einige Implementierungsdetails an die untergeordneten Klassen weitergeben möchte, ansonsten verwende ich Schnittstellen.

Natürlich sind abstrakte Klassen nicht nur nützlich, um eine Implementierung zu erzwingen, sondern auch, um einige spezifische Details mit vielen verwandten Klassen zu teilen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X