目录
今天来详细学习一下C#面向对象的三大特性:多态。
多态
多态(Polymorphism)是面向对象编程(OOP)中的一个核心概念,它允许对象以不同的方式表现出不同的行为。通过多态,子类可以在继承父类的方法时,修改或扩展父类的行为,甚至在运行时决定调用哪个类的方法,这使得程序更加灵活和可扩展。
1. 多态的概念
多态字面意思是“多种形态”,在面向对象编程中,多态指的是同一个方法或操作可以作用于不同的对象,并表现出不同的行为。
多态有两种主要形式
1)编译时多态(静态多态):主要通过方法重载和方法隐藏来实现。
2)运行时多态(动态多态):主要通过方法重写和接口实现来实现。
2. 多态的实现方式
1) 方法重载(编译时多态)
方法重载是指在同一个类中,可以定义多个相同名字但参数不同的方法。编译器会根据传入的参数类型和数量来决定调用哪个方法。
如,让Print方法根据不同的参数类型表现出不同的行为。
public class Printer
{
//方法重载:不同的参数类型
public void Print(string text)
{
Console.WriteLine("Printing text: " + text);
}
public void Print(int number)
{
Console.WriteLine("Printing number: " + number);
}
public void Print(double number)
{
Console.WriteLine("Printing double: " + number);
}
}
public class Program
{
public static void Main()
{
Printer printer = new Printer();
printer.Print("Hello World!"); //调用 Print(string)
printer.Print(123); //调用 Print(int)
printer.Print(45.67); //调用 Print(double)
}
}
2) 方法隐藏(编译时多态)
方法隐藏通常指的是在子类中定义一个与父类方法签名相同的方法,这会导致子类的方法隐藏父类的方法。与方法重写不同,方法隐藏在编译时就确定了哪个方法。使用new关键字来指示这是一个方法隐藏,而不是方法重写。
如,一个父类Animal和一个子类Dog,在子类中定义了一个与父类方法签名相同的方法
using System;
class Animal
{
public void Sound()
{
Console.WriteLine("Animal makes a sound.");
}
}
class Dog : Animal
{
//隐藏父类的 Sound 方法
public new void Sound()
{
Console.WriteLine("Dog WangWang.");
}
}
class Program
{
static void Main()
{
Animal animal = new Dog();
animal.Sound();//输出: Animal makes a sound.
Dog dog = new Dog();
dog.Sound();//输出: Dog WangWang.
}
}
3) 方法重写(运行时多态)
方法重写是指子类重写父类的虚方法或抽象方法,从而改变父类方法的实现。运行时多态基于方法重写机制,允许通过父类引用调用子类的实现,实际调用的会是子类的重写版本,而不是父类的原始方法。
①虚方法(virtual)重写
虚方法重写是指在子类中重写父类的虚方法。
如,Animal类中的MakeSound方法使用virtual关键字声明,这意味着Dog类可以重写该方法。animal.MakeSound()在运行时会调用Dog类中的重写方法,而不是Animal类中的原始方法,这是因为方法重写发生在运行时,是基于对象的实际类型(Dog)进行动态绑定的
using System;
class Animal
{
//虚方法,允许派生类重写
public virtual void MakeSound()
{
Console.WriteLine("Animal makes a sound.");
}
}
class Dog : Animal
{
//重写基类的虚方法
public override void MakeSound()
{
Console.WriteLine("Dog WangWang.");
}
}
class Program
{
static void Main()
{
Animal animal = new Dog();//父类引用指向子类对象
animal.MakeSound();//输出: Dog WangWang.
}
}
②抽象方法(abstract)重写
抽象方法重写是指子类实现父类抽象方法。父类抽象方法没有实现,子类必须提供具体实现。
如,Animal类中有一个抽象方法MakeSound(),并且Dog类必须实现这个方法。与虚方法重写类似,animal.MakeSound()在运行时会根据animal实际的类型(Dog)来调用Dog类中的重写方法。
using System;
abstract class Animal
{
//抽象方法,没有实现
public abstract void MakeSound();
}
class Dog : Animal
{
//重写抽象方法,必须实现具体的功能
public override void MakeSound()
{
Console.WriteLine("Dog WangWang.");
}
}
class Program
{
static void Main()
{
Animal animal = new Dog();//父类引用指向子类对象
animal.MakeSound();//输出: Dog WangWang.
}
}
4) 接口实现(运行时多态)
接口是一个定义一组方法签名的合同,类可以通过实现接口来提供这些方法的具体实现。接口的实现也支持多态,可以通过接口类型引用来调用不同类的实现。
如,IDrawable 接口定义了Draw方法,Circle和Rectangle类实现了该接口。通过接口类型IDrawable引用,可以实现对不同形状对象的多态调用。
public interface IDrawable
{
void Draw();
}
public class Circle : IDrawable
{
public void Draw()
{
Console.WriteLine("Drawing a circle.");
}
}
public class Rectangle : IDrawable
{
public void Draw()
{
Console.WriteLine("Drawing a rectangle.");
}
}
public class Program
{
public static void Main()
{
IDrawable shape1 = new Circle();
IDrawable shape2 = new Rectangle();
shape1.Draw();//输出:Drawing a circle.
shape2.Draw();//输出:Drawing a rectangle.
}
}
3. 多态的特点
1)运行时动态绑定。多态的核心特性是方法的动态绑定。方法的调用并不是在编译时确定的,而是在运行时根据对象的实际类型来确定调用哪个版本的方法。
2)提高代码灵活性和可扩展性。通过多态,可以编写更加通用和灵活的代码。比如,在上述示例中,无论传入什么类型的IDrawable对象,都能通过统一的Draw方法进行处理,而不需要关心具体类型。
3)代码复用。多态允许代码在不同的上下文中复用。通过父类或接口的引用指向不同的子类对象,我们可以写出更加通用的代码。
4)接口与抽象类的应用:多态的实现通常通过接口和抽象类来实现,尤其是在设计模式中,接口和抽象类有助于提供统一的操作接口,增强代码的可维护性。
4. 多态的优点
1)代码灵活性和可扩展性:可以编写更加通用和灵活的代码,支持更多类型的扩展。
2)减少重复代码:通过父类引用或接口引用,可以避免为不同子类编写重复的代码。
3)增加程序的可维护性:不同的类实现相同的接口或基类,容易进行扩展和修改而不影响现有代码。
4)通过正确使用多态,程序员可以实现更加高效和易于维护的代码结构,增强系统的灵活性和可扩展性。
5. 总结
多态是面向对象编程中的一个重要特性,它允许通过父类或接口类型的引用,指向不同子类的对象,并根据实际对象类型动态决定调用哪个方法。多态可以通过方法重载(编译时多态)、方法重写和接口实现(运行时多态)来实现。
好了,本次的分享到这里就结束啦,希望对你有所帮助~