探索基于接口的多态性
基于接口的多态性允许你定义类必须实现的协定,使你能够在不依赖于类继承的情况下实现多态行为。 接口定义类必须实现的一组方法和属性,但不提供任何实现详细信息。 类可以实现多个接口,允许它们为应用程序的不同方面定义行为。
若要探索基于接口的多态性,可以从与上一单元中基于继承的多态性方案类似的方案开始。
请考虑以下代码示例,该示例演示 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();
}
}
}
在此代码示例中,通过定义包含 ISound 方法的 MakeSound 接口来演示基于接口的多态性。 Dog、Cat和 Cow 类通过提供 ISound 方法的自己的实现来实现 MakeSound 接口。 Main 方法创建一个由 ISound 对象构成的数组,并将 Dog、Cat和 Cow 的实例分配给数组。 foreach 循环循环访问数组并调用每个对象的 MakeSound 方法,演示多态行为。
此时,基于接口的多态性可能与基于继承的多态性可互换。 使用加法类类型更新示例代码有助于演示差异。
请考虑以下更新的代码示例:
// 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();
}
}
}
此更新的示例代码包括实现 Doorbell 接口的另外两个类,CarHorn 和 ISound。 这些附加类有助于演示基于接口的多态性在定义未绑定到特定类层次结构的行为方面更大的灵活性。
基于接口的多态性提供了其他优势,例如允许类实现多个接口并定义特定功能的协定。 接口可用于定义可在不同类之间共享的常见行为,从而启用多态性,而无需通用基类。
请考虑以下代码,该代码演示具有单个接口和多个接口的对象:
// 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();
}
}
实现基于接口的多态性时避免常见的陷阱
当你的目标是基于接口的多态性时,下面是一些要避免的事项以及一些需要确保的事项。
- 避免实现不相关的接口。
- 避免接口中的默认实现。 虽然 C# 允许接口中的默认实现,但可能会导致混淆并降低接口用途的清晰度。 首选共享实现的抽象类。
- 避免过度复杂化接口层次结构。 保持接口层次结构简单,避免深层继承链。 复杂的层次结构可以使代码难以理解和维护。
- 确保遵循接口隔离原则 (ISP)。 ISP 指出,不应强制任何客户端依赖它不使用的方法。 创建更小、更具体的接口,而不是一个大型接口。
总结
基于接口的多态性允许你定义类必须实现的协定,使你能够在不依赖于类继承的情况下实现多态行为。 通过实现接口,可以创建灵活且可维护的代码,从而促进松散耦合和代码可重用性。 接口提供了一种定义可跨不同类共享的常见行为的方法,允许你通过通用接口处理不同类型的对象。 通过了解基于接口的多态性,可以设计更易于维护和演变的模块化和可扩展应用程序。