C#中面向对象编程机制之多态学习笔记
C#的多态性:
我的理解是:同一个操作,作用于不同的对象时,会有不同的结果,即同一个方法根据需要,作用于不同的对象时,会有不同的实现。
C#的多态包括:接口多态,继承多态。
其中继承多态又包括通过虚拟方法实现的多态和通过抽象方法实现的多态性
例如:基类动物都有吃的方法,但是不同的动物吃的东西就会不一样,例如狼吃肉,羊吃草,这样“吃”的这个方法就要在派生类里面重新实现以下,运行时,通过指向基类的指针,来调用实现派生类中的方法。
接下来举例实现多态性。
1. 接口多态性
把动物“吃”的方法放到一个接口(IAnimal)里,然后让具体的动物类(Wolf/Sheep)继承这个接口,并根据自己的需要实现这个接口。
代码实现:
class Program {
static void Main(string[] args) {
new Wolf().Eat();
new Sheep().Eat();
}
}
public class Wolf : IAnimal {
//多态实现
public void Eat() {
Console.WriteLine("狼吃肉!");
}
}
public class Sheep : IAnimal {
//多态实现
public void Eat() {
Console.WriteLine("羊吃草!");
}
}
//接口
public interface IAnimal {
void Eat();
}
接口的多态性就是当不同的类继承了相同的接口以后,都要根据自己的需要重新实现继承的接口,这样同样的方法签名在不同的类中就会实现不同的操作。
2. 继承的多态性
2.1.通过虚拟方法实现的多态(virtual,override)
首先要在基类中实现virtual方法,然后在派生类中根据自己的需要用override重写virtual方法。如果不希望这个方法被继续重写,则把这个方法写成sealed方法。
virtual方法必须在基类中实现。
代码实现:
class Program {
static void Main(string[] args) {
new Wolf().Eat();
new Sheep().Eat();
new Goat().Eat();
}
}
public class Wolf : Animal {
//多态实现
public override void Eat() {
base.Eat();
Console.WriteLine("狼吃肉!");
}
}
public class Sheep : Animal {
//多态实现
public override void Eat() {
base.Eat();
Console.WriteLine("羊吃草!");
}
}
public class Goat : Sheep {
//多态实现被终结,此Eat方法不能被override,因为用sealed了
public sealed override void Eat() {
//base.Eat();
Console.WriteLine("山羊吃草!");
}
}
//基类实现虚方法
public class Animal {
public virtual void Eat() { }
}
2.2.通过抽象方法实现的多态(abstract,override)
抽象方法必须定义在抽象类里。抽象类不能被创建实例。
基类中的抽象方法只能被声明,不需要实现,所以派生类中重写抽象方法的时候没有base方法。
代码实现如下:
class Program {
static void Main(string[] args) {
new Wolf().Eat();
new Sheep().Eat();
new Goat().Eat();
}
}
public class Wolf : Animal {
//多态实现
public override void Eat() {
Console.WriteLine("狼吃肉!");
}
}
public class Sheep : Animal {
//多态实现
public override void Eat() {
Console.WriteLine("羊吃草!");
}
}
public class Goat : Sheep {
//多态实现被终结,此Eat方法不能被override,因为用sealed了
public sealed override void Eat() {
Console.WriteLine("山羊吃草!");
}
}
//基类只需声明方法
public abstract class Animal {
public abstract void Eat();
}
总结:
1.虚方法重写的时候可以有base方法(base.Eat()),抽象方法重写的时候没有base方法,原因是:虚方法必须在基类中实现,抽象方法只在基类中声明,不需要实现。
2.派生类中可以 不重写虚方法的实现,但是派生类必须重写抽象方法的实现,原因同1.
3.包含虚方法的非抽象类可以被创建实例(对象),但是包含抽象方法的抽象类不能被创建实例。
4.继承接口的派生类必须实现接口的方法,因为接口也是只负责声明方法,不负责实现。
5.接口的多态性不需要用override重写方法。