前言
上篇博客说了面向对象三大特性中的前两个,对于最不容易理解的第三大特性——多态,在这篇博客中就会有简单的描述。很多人都不明白面向对象中多态的真正作用是什么,通过下面几个简单的小例子,让我们来感受下多态的威力。
定义
多态表示不同的对象可以执行相同的动作,但要通过它们自己的实现代码来执行。
简单来说,就是子类继承父类,以父类的身份出现,在工作时以自己的方式来实现,但是,子类以父类身份出现时,子类特有的属性和方法不可以使用。
用法
相关概念
虚方法
为了使子类的实例完全接替来自父类的类成员,父类必须将该成员声明为虚拟的,通过在该成员的返回类型之前添加virtual关键字来实现。
方法覆写
子类可以选择使用override关键字将父类实现替换为它自己的实现。
实例
接着上篇博客的例子,由于Cat和Dog都有Shout的方法,只是叫的声音不同,所以我们可以让Animal有一个Shout的虚方法,然后让Cat和Dog去重写这个Shout,在使用的时候,就可以用Cat或者Dog来代替Animal叫,达到多态的目的。
class Animal
{
public virtual string Shout()
{
return "";
}
}//修饰符中增加了一个虚方法<virtual>,表示此方法可以被子类重写。
接下来,我们让猫咪叫。
class Cat:Animal
{
public Cat():base()
{}
public Cat(string name):base(name)
{}
public override string Shout()
{
string result = "";
for (int i = 0;i < shoutNum;i++)
result +="喵,";
return "我的名字叫" + name + "" + result;
}
}
让狗狗叫。
class Dog:Animal
{
public Dog():base()
{}
public Dog(string name):base(name)
{}
public override string Shout()
{
string result = "";
for (int i = 0;i < shoutNum;i++)
result +="汪,";
return "我的名字叫" + name + "" + result;
}
}
我们发现,实现两个动物叫的代码仅仅有一点不同,它们继承了同一个类,表现出了不同的形式。接下来看客户端代码。
private Animal[] arrayanimal;//声明一个动物数组
private void button1_Click(object sender, EventArgs e)
{
arrayAnimal = new Animal[5];//实例化最多可报名5个的动物数组对象
arrayAnimal[0] = new Cat ("小花");
arrayAnimal[1] = new Dog ("阿毛");
arrayAnimal[2] = new Dog ("小黑");
arrayAnimal[3] = new Cat ("娇娇");
arrayAnimal[4] = new Cat ("咪咪");
}
//叫声比赛
private void button2_Click(object sender, EventArgs e)
{
foreach (Animal item in arrayAnimal)
{
MessageBox.Show(item.Shout());
}
}
结果就是,点击叫声比赛后,弹出五个消息框,是猫叫就喵,狗叫就汪。
总结
在这里,Animal作为一个父类,Cat和Dog类就是Animal的子类,子类代替父类进行Shout,但是Cat叫出来的是“喵”,Dog叫出来的是“汪”,这就是所谓的不同的对象可以执行相同的动作,但要通过它们自己的实现代码才行。要注意的是,对象的声明必须是父类,实例化的对象是子类,这样才能实现多态。
多态的原理是当方法被调用时,无论对象是否被转换为其父类,都只有位于对象继承链最末端的方法实现会被调用,即,虚方法是按照其运行时的类型而非编译时类型进行动态绑定调用的。