Utforsk grensesnittbasert polymorfisme
Med grensesnittbasert polymorfisme kan du definere en kontrakt som klassene må implementere, slik at du kan oppnå polymorf atferd uten å stole på klassearv. Grensesnitt definerer et sett med metoder og egenskaper som en klasse må implementere, men gir ingen implementeringsdetaljer. Klasser kan implementere flere grensesnitt, slik at de kan definere virkemåte for ulike aspekter av programmet.
Hvis du vil utforske grensesnittbasert polymorfisme, kan du begynne med et scenario som ligner på det arvebaserte polymorfismescenariet fra den forrige enheten.
Vurder følgende kodeeksempel som demonstrerer grensesnittbasert polymorfisme 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 kodeeksempelet demonstreres grensesnittbasert polymorfisme ved å definere et ISound grensesnitt som inneholder en MakeSound metode. Klassene Dog, Catog Cow implementerer ISound-grensesnittet ved å gi sine egne implementeringer av MakeSound metoden. Metoden Main oppretter en matrise med ISound objekter og tilordner forekomster av Dog, Catog Cow til matrisen. Den foreach løkke gjentas over matrisen og kaller MakeSound metoden på hvert objekt, som demonstrerer polymorf atferd.
På dette punktet kan grensesnittbasert polymorfisme virke utskiftbar med arvebasert polymorfisme. Oppdatering av eksempelkoden med tilleggsklassetype skal bidra til å demonstrere forskjellen.
Vurder følgende oppdaterte 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 oppdaterte eksempelkoden inneholder to ekstra klasser, Doorbell og CarHorn, som implementerer ISound-grensesnittet. Disse ekstra klassene bidrar til å demonstrere grensesnittbasert polymorfismes større fleksibilitet i å definere atferd som ikke er knyttet til et bestemt klassehierarki.
Grensesnittbasert polymorfisme gir flere fordeler, for eksempel å tillate klasser å implementere flere grensesnitt og definere kontrakter for spesifikk funksjonalitet. Grensesnitt kan brukes til å definere vanlig virkemåte som kan deles på tvers av ulike klasser, noe som muliggjør polymorfisme uten behov for en felles basisklasse.
Vurder følgende kode som demonstrerer objekter med enkle og flere grensesnitt:
// 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();
}
}
Unngå vanlige fallgruver ved implementering av grensesnittbasert polymorfisme
Når målet ditt er grensesnittbasert polymorfisme, er det noen ting du bør unngå, og noen ting å sikre:
- Unngå å implementere ikke-relaterte grensesnitt.
- Unngå standardimplementeringer i grensesnitt. Selv om C# tillater standardimplementeringer i grensesnitt, kan det føre til forvirring og redusere klarheten i grensesnittets formål. Foretrekker abstrakte klasser for delte implementeringer.
- Unngå å overkomplisere grensesnitthierarkier. Hold grensesnitthierarkier enkle og unngå dype arvekjeder. Komplekse hierarkier kan gjøre koden vanskeligere å forstå og vedlikeholde.
- Sørg for at du følger grensesnittets segregeringsprinsipp (ISP). Isp sier at ingen klient skal bli tvunget til å stole på metoder den ikke bruker. Opprett mindre, mer spesifikke grensesnitt i stedet for ett stort grensesnitt.
Sammendrag
Med grensesnittbasert polymorfisme kan du definere kontrakter som klassene må implementere, slik at du kan oppnå polymorf atferd uten å stole på klassearv. Ved å implementere grensesnitt kan du opprette fleksibel og vedlikeholdbar kode som fremmer løs kobling og gjenbruk av kode. Grensesnitt gir en måte å definere vanlig virkemåte som kan deles på tvers av ulike klasser, slik at du kan arbeide med objekter av forskjellige typer gjennom et felles grensesnitt. Ved å forstå grensesnittbasert polymorfisme kan du utforme modulære og utvidbare programmer som er enklere å vedlikeholde og utvikle seg over tid.