多态性是面向对象编程(OOP)的一个重要特性,它允许一个接口有多个实现方式。在C#中,多态性主要通过方法重写(Override)和接口实现来实现。理解多态性有助于编写更灵活和可扩展的代码。
1. 方法重写(Override)
方法重写是多态性的一个重要表现形式,它允许子类提供特定的实现来替代基类中的方法。基类中的方法必须使用virtual
关键字标记为虚方法,子类使用override
关键字来重写该方法。
示例:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Some generic animal sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
}
class Program
{
static void Main(string[] args)
{
Animal myAnimal = new Animal();
myAnimal.MakeSound(); // 输出 Some generic animal sound
Dog myDog = new Dog();
myDog.MakeSound(); // 输出 Bark
Cat myCat = new Cat();
myCat.MakeSound(); // 输出 Meow
Animal anotherDog = new Dog();
anotherDog.MakeSound(); // 输出 Bark
}
}
在这个示例中,Dog
和Cat
类重写了Animal
类的MakeSound
方法,展示了多态性的特性。
2. 抽象类与抽象方法
抽象类不能被实例化,通常作为其他类的基类。抽象方法没有实现,必须在派生类中重写。抽象类使用abstract
关键字定义,抽象方法也使用abstract
关键字定义。
示例:
public abstract class Shape
{
public abstract double GetArea();
public void DisplayArea()
{
Console.WriteLine($"Area: {GetArea()}");
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public override double GetArea()
{
return Math.PI * Radius * Radius;
}
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public override double GetArea()
{
return Width * Height;
}
}
class Program
{
static void Main(string[] args)
{
Circle circle = new Circle(5);
circle.DisplayArea(); // 输出 Area: 78.53981633974483
Rectangle rectangle = new Rectangle(4, 5);
rectangle.DisplayArea(); // 输出 Area: 20
}
}
在这个示例中,Circle
和Rectangle
类继承自Shape
抽象类,并实现了GetArea
方法。
3. 接口与多态性
接口定义了一个类应该具有的一组方法和属性,但不提供具体实现。实现接口的类必须提供接口中定义的所有成员的实现。接口实现也是多态性的一种表现形式。
示例:
public interface IAnimal
{
void MakeSound();
}
public class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Bark");
}
}
public class Cat : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Meow");
}
}
class Program
{
static void Main(string[] args)
{
IAnimal myDog = new Dog();
myDog.MakeSound(); // 输出 Bark
IAnimal myCat = new Cat();
myCat.MakeSound(); // 输出 Meow
}
}
在这个示例中,Dog
和Cat
类实现了IAnimal
接口,并提供了MakeSound
方法的具体实现。
4. 接口与继承
接口可以继承其他接口,这使得接口更加灵活和可重用。
示例:
public interface IAnimal
{
void Eat();
}
public interface IFlyable : IAnimal
{
void Fly();
}
public class Bird : IFlyable
{
public void Eat()
{
Console.WriteLine("Eating...");
}
public void Fly()
{
Console.WriteLine("Flying...");
}
}
class Program
{
static void Main(string[] args)
{
Bird bird = new Bird();
bird.Eat(); // 输出 Eating...
bird.Fly(); // 输出 Flying...
}
}
在这个示例中,IFlyable
接口继承了IAnimal
接口,Bird
类实现了IFlyable
接口,并提供了所有继承成员的实现。
5. 多态性的优势
多态性提高了代码的灵活性和可扩展性。通过使用基类引用或接口引用,可以编写更通用的代码,减少代码的重复,并且可以轻松地扩展新功能。
示例:
public abstract class Shape
{
public abstract double GetArea();
}
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public override double GetArea()
{
return Math.PI * Radius * Radius;
}
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public override double GetArea()
{
return Width * Height;
}
}
class Program
{
static void Main(string[] args)
{
List<Shape> shapes = new List<Shape>
{
new Circle(5),
new Rectangle(4, 5)
};
foreach (Shape shape in shapes)
{
Console.WriteLine($"Area: {shape.GetArea()}");
}
}
}
在这个示例中,我们创建了一个包含不同形状对象的列表,并通过基类引用调用GetArea
方法,展示了多态性的优势。
6. 多态性与泛型
多态性可以与泛型结合使用,进一步提高代码的灵活性和可重用性。
示例:
public interface IShape
{
double GetArea();
}
public class Circle : IShape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public double GetArea()
{
return Math.PI * Radius * Radius;
}
}
public class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public double GetArea()
{
return Width * Height;
}
}
public class ShapePrinter<T> where T : IShape
{
public void PrintArea(T shape)
{
Console.WriteLine($"Area: {shape.GetArea()}");
}
}
class Program
{
static void Main(string[] args)
{
Circle circle = new Circle(5);
Rectangle rectangle = new Rectangle(4, 5);
ShapePrinter<Circle> circlePrinter = new ShapePrinter<Circle>();
circlePrinter.PrintArea(circle); // 输出 Area: 78.53981633974483
ShapePrinter<Rectangle> rectanglePrinter = new ShapePrinter<Rectangle>();
rectanglePrinter.PrintArea(rectangle); // 输出 Area: 20
}
}
在这个示例中,我们定义了一个泛型类ShapePrinter
,它可以打印实现了IShape
接口的任何形状的面积。
结束语
C#中的多态性概念,包括方法重写、抽象类与抽象方法、接口与多态性、接口继承、多态性的优势以及多态性与泛型的结合。