文章部分内容来自:作者:Kevin 出处:http://zhangkai2237.cnblogs.com/
- 方法名必须相同
- 参数列表必须不相同
- 返回值类型可以不相同
public void Sleep() { Console.WriteLine("Animal睡觉"); } public int Sleep(int time) { Console.WriteLine("Animal{0}点睡觉", time); return time; }
- 相同的方法名
- 相同的参数列表
- 相同的返回值。
public virtual void EatFood() { Console.WriteLine("Animal吃东西"); }
子类中的定义:
public override void EatFood() { Console.WriteLine("Cat吃东西"); //base.EatFood(); }
tips:经常有童鞋问重载和重写的区别,而且网络上把这两个的区别作为C#做常考的面试题之一。实际上这两个概念完全没有关系,仅仅都带有一个“重”字。他们没有在一起比较的意义,仅仅分辨它们不同的定义就好了。 |
public virtual void EatFood() { Console.WriteLine("Animal吃东西"); }
Animal a = new Animal(); a.EatFood();
public abstract class Biology { public abstract void Live(); } public class Animal : Biology { public override void Live() { Console.WriteLine("Animal重写的抽象方法"); //throw new NotImplementedException(); } }
虚方法和抽象方法的区别是:因为抽象类无法实例化,所以抽象方法没有办法被调用,也就是说抽象方法永远不可能被实现。 |
public void Sleep() { Console.WriteLine("Animal Sleep"); }
new public void Sleep() { Console.WriteLine("Cat Sleep"); }
或者为:
public new void Sleep() { Console.WriteLine("Cat Sleep"); }
public abstract class Biology { public abstract void Live(); } public class Animal : Biology { public override void Live() { Console.WriteLine("Animal重写的Live"); //throw new NotImplementedException(); } public void Sleep() { Console.WriteLine("Animal Sleep"); } public int Sleep(int time) { Console.WriteLine("Animal在{0}点Sleep", time); return time; } public virtual void EatFood() { Console.WriteLine("Animal EatFood"); } } public class Cat : Animal { public override void EatFood() { Console.WriteLine("Cat EatFood"); //base.EatFood(); } new public void Sleep() { Console.WriteLine("Cat Sleep"); } //public new void Sleep() //{ // Console.WriteLine("Cat Sleep"); //} } public class Dog : Animal { public override void EatFood() { Console.WriteLine("Dog EatFood"); //base.EatFood(); } }
class Program { static void Main(string[] args) { //Animal的实例 Animal a = new Animal(); //Animal的实例,引用派生类Cat对象 Animal ac = new Cat(); //Animal的实例,引用派生类Dog对象 Animal ad = new Dog(); //Cat的实例 Cat c = new Cat(); //Dog的实例 Dog d = new Dog(); //重载 a.Sleep(); a.Sleep(23); //重写和虚方法 a.EatFood(); ac.EatFood(); ad.EatFood(); //抽象方法 a.Live(); //隐藏方法 a.Sleep(); ac.Sleep(); c.Sleep(); Console.ReadKey(); } }
//重载 a.Sleep(); a.Sleep(23);
//重写和虚方法 a.EatFood(); ac.EatFood(); ad.EatFood();
//抽象方法 a.Live();
//隐藏方法 a.Sleep(); ac.Sleep(); c.Sleep();
把动物“吃”的方法放到一个接口(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.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重写方法。