什么是多态?
通俗的理解就是:不同的对象收到相同的消息时,会产生不同的行为。
多态的两种体现形式
1.重写父类方法
1)使用 new 关键字,隐藏父类方法
当子类的方法与父类的方法同名时,可以在子类方法的修饰符后面加 new 关键字,这种是将父类的方法隐藏,我的理解是子类中仍然有继承下来的父类方法,只不过是隐藏起来。可以根据情况,想调用父类的方法就调用父类的方法,想调用自己的方法就调用自己的方法。
如果不用 new 关键字,VS 会自动默认加上 new 关键字,但是会提示你:如果有意隐藏,请使用 new 关键字。
public class Person
{
public void Show()
{
Console.WriteLine("我是人别害怕");
}
}
public class Teacher : Person
{
public new void Show()
{
Console.WriteLine("我是老师别害怕");
}
}
class Program
{
static void Main(string[] args)
{
Teacher t = new Teacher();
t.Show();
}
}
//output:
//我是老师别害怕
2)虚方法重写
将父类中的方法用 virtual 修饰,子类中用 override 关键字重写父类方法
public class Person
{
public virtual void Show()
{
Console.WriteLine("我是人别害怕");
}
}
public class Teacher : Person
{
public override void Show()
{
Console.WriteLine("我是老师别害怕");
}
}
注意:
①虚方法不能用 static 修饰
②虚方法不能用 private 修饰,因为虚方法就是让子类来重写的,如果声明为 private,子类就无法重写,所以不能是私有的
③虚方法中要有方法体,可以被子类重写,也可以不被子类重写
3)抽象方法重写
①什么是抽象方法呢?
抽象方法:即在父类方法的修饰符后加 abstract 关键字,抽象方法没有方法体,只能存在于抽象类中。一旦子类继承了抽象类,则抽象类中的抽象方法必须在子类中重写。
②重写父类抽象方法
public class Person
{
public abstract void Show();
}
public class Teacher : Person
{
public override void Show()
{
Console.WriteLine("我是老师别害怕");
}
}
★看完以上三种重写方法,有没有什么疑问呢?使用 new 关键字隐藏和使用 override 重写有什么不同呢?
1.首先来看一下它们的定义:
new(隐藏):子类只是把父类中的同名方法隐藏了,其实在子类中还存在父类的方法。如果需要用到父类的方法,还可以再调用父类的方法,也可以调用自己的方法。
override(重写):子类将父类中的方法重写了,在子类中已经不存在父类的方法了,调用的时候只能调用自己的方法。
2.什么意思呢?
如果使用 new 关键字隐藏父类的方法,即定义的变量为父类则调用父类方法,定义的变量为子类则调用子类的方法,调用哪个方法,取决于定义的变量类型。
如果使用 override 关键字重写父类方法,即不管定义的变量类型为父类还是子类时,但 new 的是子类对象时,皆调用子类的方法。调用哪个方法,取决于 new 的对象实例
3.下面来看一下例子
//使用 new 关键字
public class Person
{
public void Show()
{
Console.WriteLine("我是人别害怕");
}
}
public class Teacher : Person
{
public new void Show()
{
Console.WriteLine("我是老师别害怕");
}
}
class Program
{
static void Main(string[] args)
{
Person p = new Teacher();
p.show(); //调用父类方法
Teacher t = new Teacher();
t.Show(); //调用子类自己的方法
((Person)t).show(); //仍然调用父类方法
}
}
//output:
//我是人别害怕
//我是老师别害怕
//我是人别害怕
//调用父类方法还是调用子类方法,取决于定义的变量类型
//使用 override 重写父类方法
public class Person
{
public virtual void Show()
{
Console.WriteLine("我是人别害怕");
}
}
public class Teacher : Person
{
public override void Show()
{
Console.WriteLine("我是老师别害怕");
}
}
public class Student : Person
{
public override void Show()
{
Console.WriteLine("我是学生别害怕");
}
}
class Program
{
static void Main(string[] args)
{
//下面三个变量不能同时存在,因为同名了,读者在测试的时候,可选择替换后面的对象
Person p = new Person();
p.show(); //调用Person类方法
Person p = new Teacher();
p.show(); //调用Teacher类方法
Person p = new Student();
p.show(); //调用Student类方法
}
}
//output:
//我是人别害怕
//我是老师别害怕
//我是学生别害怕
//调用哪个方法,取决于 new 的对象,这也就体现了多态,即对象不同,方法相同,但是行为却不同
★虚方法和抽象方法的比较
2.接口
1)什么是接口?
接口也是多态的一种体现。接口是一种规范,它规定了能干什么,如果某一个类实现了接口,就必须实现接口中的方法。
2)接口是干什么的?
由于类继承的单根性,无法继承多个类,但是可以实现多个接口。每个接口的功能单一,这就弥补了继承的不足。
3)接口示例
interface IFly
{
void IFly();
}
public class Teacher:Person,IFly
{
public void IFly()
{
Console.WriteLine("我是老师,我会飞");
}
}
public class Student : IFly
{
public void IFly()
{
Console.WriteLine("我是学生,我也会飞");
}
}
class Program
{
static void Main(string[] args)
{
IFly ifly = new Teacher(); //多态的另一种体现
ifly.IFly();
IFly ifly = new Student();
ifly.IFly();
}
}
//output:
//我是老师,我会飞
//我是学生,我也会飞