Erforschung von schnittstellenbasiertem Polymorphismus
Mithilfe der schnittstellenbasierten Polymorphie können Sie einen Vertrag definieren, den Klassen implementieren müssen, sodass Sie polymorphes Verhalten erzielen können, ohne sich auf die Klassenvererbung zu verlassen. Schnittstellen definieren eine Reihe von Methoden und Eigenschaften, die eine Klasse implementieren muss, stellen jedoch keine Implementierungsdetails bereit. Klassen können mehrere Schnittstellen implementieren, sodass sie das Verhalten für verschiedene Aspekte der Anwendung definieren können.
Um den schnittstellenbasierten Polymorphismus zu erkunden, können Sie mit einem Szenario beginnen, das dem vererbungsbasierten Polymorphismusszenario aus der vorherigen Einheit ähnelt.
Betrachten Sie das folgende Codebeispiel, das den schnittstellenbasierten Polymorphismus in C# veranschaulicht:
// Define an interface
public interface ISound
{
void MakeSound();
}
// Implement the interface in different classes
public class Dog : ISound
{
public void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
public class Cat : ISound
{
public void MakeSound()
{
Console.WriteLine("The cat meows.");
}
}
public class Cow : ISound
{
public void MakeSound()
{
Console.WriteLine("The cow moos.");
}
}
class Program
{
static void Main()
{
// Create an array of Animal myObjects
ISound[] myObjects = new ISound[3];
ISound object1 = new Dog();
ISound object2 = new Cat();
ISound object3 = new Cow();
myObjects[0] = object1;
myObjects[1] = object2;
myObjects[2] = object3;
// Demonstrate polymorphism
foreach (ISound currentObject in myObjects)
{
currentObject.MakeSound();
}
}
}
In diesem Codebeispiel wird der schnittstellenbasierte Polymorphismus veranschaulicht, indem eine ISound Schnittstelle definiert wird, die eine MakeSound Methode enthält. Die Klassen Dog, Catund Cow implementieren die ISound Schnittstelle, indem sie ihre eigenen Implementierungen der MakeSound-Methode bereitstellen. Die Main-Methode erstellt ein Array von ISound Objekten und weist Instanzen von Dog, Catund Cow dem Array zu. Die foreach Schleife durchläuft das Array und ruft die MakeSound-Methode für jedes Objekt auf und veranschaulicht das polymorphe Verhalten.
An diesem Punkt kann der schnittstellenbasierte Polymorphismus mit vererbungsbasiertem Polymorphismus austauschbar sein. Das Aktualisieren des Beispielcodes mit dem Zusätzlichen Klassentyp sollte dazu beitragen, den Unterschied zu veranschaulichen.
Betrachten Sie das folgende aktualisierte Codebeispiel:
// Define an interface
public interface ISound
{
void MakeSound();
}
// Implement the interface in different classes
public class Dog : ISound
{
public void MakeSound()
{
Console.WriteLine("The dog barks.");
}
}
public class Cat : ISound
{
public void MakeSound()
{
Console.WriteLine("The cat meows.");
}
}
public class Cow : ISound
{
public void MakeSound()
{
Console.WriteLine("The cow moos.");
}
}
public class Doorbell : ISound
{
public void MakeSound()
{
Console.WriteLine("The doorbell rings.");
}
}
public class CarHorn : ISound
{
public void MakeSound()
{
Console.WriteLine("The car horn honks.");
}
}
class Program
{
static void Main()
{
// Create an array of Animal myObjects
ISound[] myObjects = new ISound[3];
ISound object1 = new Dog();
ISound object2 = new Cat();
ISound object3 = new Cow();
ISound object4 = new Doorbell();
ISound object5 = new CarHorn();
myObjects[0] = object1;
myObjects[1] = object2;
myObjects[2] = object3;
myObjects[3] = object4;
myObjects[4] = object5;
// Demonstrate polymorphism
foreach (ISound currentObject in myObjects)
{
currentObject.MakeSound();
}
}
}
Dieser aktualisierte Beispielcode enthält zwei zusätzliche Klassen, Doorbell und CarHorn, die die ISound-Schnittstelle implementieren. Diese zusätzlichen Klassen helfen, die größere Flexibilität des schnittstellenbasierten Polymorphismus beim Definieren des Verhaltens zu demonstrieren, das nicht an eine bestimmte Klassenhierarchie gebunden ist.
Schnittstellenbasierte Polymorphie bietet zusätzliche Vorteile, wie die Implementierung mehrerer Schnittstellen und die Definition von Verträgen für spezifische Funktionalität. Schnittstellen können verwendet werden, um allgemeine Verhaltensweisen zu definieren, die für verschiedene Klassen freigegeben werden können, sodass Polymorphismus ohne notwendigkeit einer gemeinsamen Basisklasse möglich ist.
Betrachten Sie den folgenden Code, der Objekte mit einzelnen und mehreren Schnittstellen veranschaulicht:
// Define an interface for sound
public interface ISound
{
void MakeSound();
}
// Define an interface for movement
public interface IMovable
{
void Move();
}
// Implement the ISound and IMovable interfaces in different classes
public class Dog : ISound, IMovable
{
public void MakeSound()
{
Console.WriteLine("The dog barks.");
}
public void Move()
{
Console.WriteLine("The dog runs.");
}
}
public class Cat : ISound, IMovable
{
public void MakeSound()
{
Console.WriteLine("The cat meows.");
}
public void Move()
{
Console.WriteLine("The cat jumps.");
}
}
public class Cow : ISound, IMovable
{
public void MakeSound()
{
Console.WriteLine("The cow moos.");
}
public void Move()
{
Console.WriteLine("The cow walks.");
}
}
public class Doorbell : ISound
{
public void MakeSound()
{
Console.WriteLine("The doorbell rings.");
}
}
public class CarHorn : ISound
{
public void MakeSound()
{
Console.WriteLine("The car horn honks.");
}
}
class Program
{
static void Main()
{
// Create an array of ISound objects
ISound[] soundObjects = new ISound[5];
ISound object1 = new Dog();
ISound object2 = new Cat();
ISound object3 = new Cow();
ISound object4 = new Doorbell();
ISound object5 = new CarHorn();
soundObjects[0] = object1;
soundObjects[1] = object2;
soundObjects[2] = object3;
soundObjects[3] = object4;
soundObjects[4] = object5;
// Demonstrate polymorphism with ISound
Console.WriteLine("Demonstrating ISound polymorphism:");
foreach (ISound currentObject in soundObjects)
{
currentObject.MakeSound();
}
// Create an array of IMovable objects
IMovable[] movableObjects = new IMovable[3];
IMovable movableObject1 = new Dog();
IMovable movableObject2 = new Cat();
IMovable movableObject3 = new Cow();
movableObjects[0] = movableObject1;
movableObjects[1] = movableObject2;
movableObjects[2] = movableObject3;
// Demonstrate polymorphism with IMovable
Console.WriteLine("\nDemonstrating IMovable polymorphism:");
foreach (IMovable currentObject in movableObjects)
{
currentObject.Move();
}
// Demonstrate objects with single and multiple interfaces
Console.WriteLine("\nDemonstrating objects with single and multiple interfaces:");
Dog dog = new Dog();
Cat cat = new Cat();
Cow cow = new Cow();
Doorbell doorbell = new Doorbell();
CarHorn carHorn = new CarHorn();
dog.MakeSound();
dog.Move();
cat.MakeSound();
cat.Move();
cow.MakeSound();
cow.Move();
doorbell.MakeSound();
carHorn.MakeSound();
}
}
Vermeiden sie häufige Fallstricke bei der Implementierung von schnittstellenbasiertem Polymorphismus
Wenn Ihr Ziel schnittstellenbasiertes Polymorphismus ist, finden Sie hier einige Dinge, die Sie vermeiden sollten, und einige Dinge, die Sie sicherstellen sollten:
- Vermeiden Sie die Implementierung nicht verwandter Schnittstellen.
- Vermeiden Sie Standardimplementierungen in Schnittstellen. Während C# Standardimplementierungen in Schnittstellen zulässt, kann dies zu Verwirrung führen und die Klarheit des Zwecks der Schnittstelle verringern. Ziehen Sie abstrakte Klassen für freigegebene Implementierungen vor.
- Vermeiden Sie das Überkompilieren von Schnittstellenhierarchien. Halten Sie Schnittstellenhierarchien einfach, und vermeiden Sie tiefe Vererbungsketten. Komplexe Hierarchien können den Code schwieriger zu verstehen und zu verwalten machen.
- Stellen Sie sicher, dass Sie dem Schnittstellentrennungsprinzip (ISP) folgen. Der ISP gibt an, dass kein Client gezwungen werden sollte, von methoden abhängig zu sein, die er nicht verwendet. Erstellen Sie kleinere, spezifischere Schnittstellen anstelle einer großen Schnittstelle.
Zusammenfassung
Mithilfe der schnittstellenbasierten Polymorphie können Sie Verträge definieren, die Klassen implementieren müssen, sodass Sie polymorphes Verhalten erzielen können, ohne sich auf die Klassenvererbung zu verlassen. Durch die Implementierung von Schnittstellen können Sie flexiblen und verwendbaren Code erstellen, der lose Kopplung und Wiederverwendbarkeit von Code fördert. Schnittstellen bieten eine Möglichkeit, allgemeine Verhaltensweisen zu definieren, die über verschiedene Klassen hinweg gemeinsam genutzt werden können, sodass Sie mit Objekten unterschiedlicher Typen über eine gemeinsame Schnittstelle arbeiten können. Durch das Verständnis von schnittstellenbasiertem Polymorphismus können Sie modulare und erweiterbare Anwendungen entwerfen, die im Laufe der Zeit einfacher verwaltet und weiterentwickelt werden können.