Prozkoumání polymorfismu založeného na rozhraní
Polymorfismus založený na rozhraní umožňuje definovat kontrakt, který třídy musí implementovat, což vám umožní dosáhnout polymorfní chování bez nutnosti spoléhat se na dědičnost tříd. Rozhraní definují sadu metod a vlastností, které třída musí implementovat, ale neposkytují žádné podrobnosti implementace. Třídy mohou implementovat více rozhraní, což jim umožňuje definovat chování pro různé aspekty aplikace.
Pokud chcete prozkoumat polymorfismus založený na rozhraní, můžete začít scénářem, který je podobný scénáři polymorfismu založenému na dědičnosti z předchozí lekce.
Podívejte se na následující ukázku kódu, která demonstruje polymorfismus založený na rozhraní v jazyce 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();
}
}
}
V této ukázce kódu je polymorfismus založený na rozhraní ukázaný definováním ISound rozhraní, které zahrnuje MakeSound metodu. Třídy Dog, Cata Cow implementují ISound rozhraní tím, že poskytují vlastní implementace MakeSound metody. Metoda Main vytvoří pole objektů ISound a přiřadí k poli instance Dog, Cata Cow. Smyčka foreach iteruje přes pole a volá metodu MakeSound u každého objektu, což demonstruje polymorfní chování.
V tomto okamžiku se polymorfismus založený na rozhraní může objevit zaměnitelný s polymorfismu založeným na dědičnosti. Aktualizace ukázkového kódu s typem třídy sčítání by měla pomoct ukázat rozdíl.
Podívejte se na následující aktualizovanou ukázku kódu:
// 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();
}
}
}
Tento aktualizovaný ukázkový kód obsahuje dvě další třídy, Doorbell a CarHorn, které implementují rozhraní ISound. Tyto další třídy pomáhají předvést polymorfismus založený na rozhraní větší flexibilitu při definování chování, které není svázané s konkrétní hierarchií tříd.
Polymorfismus založený na rozhraní poskytuje další výhody, jako je například umožnění implementace více rozhraní a definování kontraktů pro konkrétní funkce. Rozhraní lze použít k definování společného chování, které lze sdílet napříč různými třídami, což umožňuje polymorfismus bez nutnosti společné základní třídy.
Představte si následující kód, který demonstruje objekty s jedním a více rozhraními:
// 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();
}
}
Vyhněte se běžným nástrahám při implementaci polymorfismu založeného na rozhraní
Pokud je vaším cílem polymorfismus založený na rozhraní, tady je několik věcí, kterým se můžete vyhnout, a některé věci, které zajistíte:
- Vyhněte se implementaci nesouvisejících rozhraní.
- Vyhněte se výchozí implementaci v rozhraních. I když jazyk C# umožňuje výchozí implementace v rozhraních, může vést k nejasnostem a snížení srozumitelnosti účelu rozhraní. Upřednostněte abstraktní třídy pro sdílené implementace.
- Vyhněte se překomplikování hierarchií rozhraní. Udržujte hierarchie rozhraní jednoduché a vyhněte se řetězům hloubkové dědičnosti. Složité hierarchie můžou znesnadnit pochopení a údržbu kódu.
- Ujistěte se, že dodržujete princip oddělení rozhraní (ISP). IsP uvádí, že žádný klient by neměl být nucen na závislosti na metodách, které nepoužívá. Vytvořte menší, konkrétnější rozhraní než jedno velké rozhraní.
Shrnutí
Polymorfismus založený na rozhraní umožňuje definovat kontrakty, které třídy musí implementovat, což vám umožní dosáhnout polymorfní chování bez nutnosti spoléhat se na dědičnost tříd. Implementací rozhraní můžete vytvořit flexibilní a udržovatelný kód, který podporuje volné párování a opakované použití kódu. Rozhraní poskytují způsob, jak definovat běžné chování, které lze sdílet napříč různými třídami, což umožňuje pracovat s objekty různých typů prostřednictvím společného rozhraní. Díky pochopení polymorfismu založeného na rozhraní můžete navrhovat modulární a rozšiřitelné aplikace, které se snadněji udržují a vyvíjejí v průběhu času.