Udforsk grænsefladebaseret polymorfi
Grænsefladebaseret polymorfi giver dig mulighed for at definere en kontrakt, som klasser skal implementere, så du kan opnå polymorf funktionsmåde uden at være afhængig af nedarvning af klassen. Grænseflader definerer et sæt metoder og egenskaber, som en klasse skal implementere, men de indeholder ingen implementeringsoplysninger. Klasser kan implementere flere grænseflader, så de kan definere funktionsmåden for forskellige aspekter af programmet.
Hvis du vil udforske grænsefladebaseret polymorfi, kan du begynde med et scenarie, der ligner det nedarvede polymorfiscenarie fra det forrige undermodul.
Se følgende kodeeksempel, der viser grænsefladebaseret polymorfi i C#:
// 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();
}
}
}
I dette kodeeksempel vises grænsefladebaseret polymorfi ved at definere en ISound grænseflade, der indeholder en MakeSound metode. Klasserne Dog, Catog Cow implementerer grænsefladen ISound ved at angive deres egne implementeringer af metoden MakeSound. Metoden Main opretter en matrix af ISound objekter og tildeler forekomster af Dog, Catog Cow til matrixen. Den foreach løkke gentager sig over matrixen og kalder metoden MakeSound for hvert objekt og demonstrerer polymorf funktionsmåde.
På dette tidspunkt kan grænsefladebaseret polymorfi forekomme udskiftelig med arvebaseret polymorfi. Hvis du opdaterer eksempelkoden med typen additionsklasse, kan det være med til at demonstrere forskellen.
Overvej følgende opdaterede kodeeksempel:
// 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();
}
}
}
Denne opdaterede eksempelkode indeholder to yderligere klasser, Doorbell og CarHorn, der implementerer grænsefladen ISound. Disse yderligere klasser hjælper med at demonstrere grænsefladebaseret polymorfis større fleksibilitet i definitionen af funktionsmåder, der ikke er knyttet til et bestemt klassehierarki.
Grænsefladebaseret polymorfi giver yderligere fordele, f.eks. at tillade klasser at implementere flere grænseflader og definere kontrakter om specifikke funktioner. Grænseflader kan bruges til at definere almindelig funktionsmåde, der kan deles på tværs af forskellige klasser, hvilket muliggør polymorfi uden behov for en fælles basisklasse.
Overvej følgende kode, der viser objekter med enkelt- og flere grænseflader:
// 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();
}
}
Undgå almindelige faldgruber ved implementering af grænsefladebaseret polymorfi
Når dit mål er grænsefladebaseret polymorfi, er her nogle ting, du skal undgå, og nogle ting, du skal sikre:
- Undgå at implementere ikke-relaterede grænseflader.
- Undgå standardimplementeringer i grænseflader. Selvom C# tillader standardimplementeringer i grænseflader, kan det føre til forvirring og reducere klarheden af grænsefladens formål. Foretrækker abstrakte klasser til delte implementeringer.
- Undgå overkomplicerende grænsefladehierarkier. Hold grænsefladehierarkier enkle, og undgå dybe nedarvningskæder. Komplekse hierarkier kan gøre det sværere at forstå og vedligeholde koden.
- Sørg for, at du følger grænsefladeadskillelsesprincippet (ISP). Internetudbyderen angiver, at ingen klient skal tvinges til at være afhængig af metoder, der ikke bruges. Opret mindre, mere specifikke grænseflader i stedet for én stor grænseflade.
Resumé
Grænsefladebaseret polymorfi giver dig mulighed for at definere kontrakter, som klasser skal implementere, så du kan opnå polymorf funktionsmåde uden at være afhængig af nedarvning af klassen. Ved at implementere grænseflader kan du oprette fleksibel og vedligeholdbar kode, der fremmer løs kobling og genbrug af kode. Grænseflader gør det muligt at definere fælles funktionsmåder, der kan deles på tværs af forskellige klasser, så du kan arbejde med objekter af forskellige typer via en fælles grænseflade. Ved at forstå grænsefladebaseret polymorfi kan du designe modulopbyggede og udvidelsesbare programmer, der er nemmere at vedligeholde og udvikle med tiden.