咱们书接上回(抽象类与接口)。
学了这么多天,包括C#的初步理解和大话设计模式的终结,越来越能感受到OO的魅力所在了。
都说编程源自生活,就是说程序设计大神们从吃饭睡觉打豆豆等一系列日常生活中找到灵感,找到解决程序设计难题的模式和方法。而我们这些小菜就只能走先体会编程思想,把编程融入生活,再从生活中继续总结和发展的道路了。
体会程序世界,你会有不一样的人生感觉!
下面将为大家倾情解说“OO引领编程”之---继承与多态。
继承篇。
1、继承简介
俗话说:龙生龙凤生凤,老鼠的儿子会打洞。从字面上理解,继承就是无偿接受先辈流传下来的东西。
在编程的世界里也一样,后一代继承前一代的非私有功能并有所发展。如果不发展,需求本身也就没有太大创新价值了。也就是说,原来的老鼠不光会打洞,还会上淘宝了!
class Program { static void Main(string[] args) { NewMouse m = new NewMouse();//实例化一个名为m的新老鼠对象 m.打洞(); m.上淘宝(); } } class OldMouse //定义一个old老鼠类,它有一个打洞的方法 { public void 打洞() { Console.WriteLine("我会打洞!"); } } class NewMouse:OldMouse //定义一个new老鼠类,继承了old老鼠类,并且有一个“上淘宝”的新方法 { public void 上淘宝() { Console.WriteLine("我会上淘宝!"); } } }
输出结果为:我会打洞!我会上淘宝!
这里的OldMouse称为基类,NewMouse称为派生类(子类)。
2、Base关键字
本来上边的这种继承已经很方便了,现在为了使我们进一步体会继承的美妙,Base关键字来了。
Base关键字用于从派生类中访问基类成员,并且可以使用Base关键字调用基类的构造函数。下面看它的使用方法。
class Program { static void Main(string[] args) { NewMouse m = new NewMouse("Jakc",5); //实例化一个名为m的新老鼠对象 //m.打洞(); //m.上淘宝(); } } class OldMouse //定义一个old老鼠类,它有一个打洞的方法 { protected string name; //定义姓名和性别变量 protected uint age; public OldMouse (string name,uint age) //吧姓名和年龄传给OldMouse { this.name = name; this.age = age; Console.WriteLine("我叫{0},我{1}岁了",name,age ); } //public void 打洞() //{ // Console.WriteLine("我会打洞!"); //} } class NewMouse : OldMouse //定义一个new老鼠类,继承了old老鼠类,并且有一个“上淘宝”的新方法 { public NewMouse (string name,uint age):base(name,age ) //调用了基类的构造函数 { } //public void 上淘宝() //{ // Console.WriteLine("我会上淘宝!"); //} }
输出:我叫Jack,我5岁了
3、override与overload
override是指重写。首先指明重写的前提:
5、不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。也就是说,用 override 修饰符重写的基类中的方法必须是 virtual, abstract 或 override 方法。
理解重写:一般派生类继承基类的方法,在派生类调用该继承方法的时候,其实是调用和执行基类的实现。但有时候我们需要更多种不同的实现(老鼠需要用不同的工具打洞),这就要用到override了。
"重写"基类方法就是修改它的实现或者说在派生类中重新编写。就是虽然他们叫同一个名,但是能干不同的事儿!(要是还觉得晦涩,看例子吧亲们!)
class Program { static void Main(string[] args) { Mouse oldm = new OldMouse(); //实例化old老鼠 Mouse newm =new NewMouse (); //实例化new老鼠 oldm.打洞("爪子"); newm.打洞("铁锹"); } } abstract class Mouse //定义一个Mouse超类 { public string tool=""; //定义打洞工具名称 public abstract void 打洞(string tool); //抽象的打洞方法 } class OldMouse :Mouse //定义一个old老鼠类,继承了老鼠类 { public override void 打洞(string tool) //重写打洞方法 { Console.WriteLine("old老鼠用{0}打洞",tool ); } } class NewMouse : Mouse //定义一个new老鼠类,继承了老鼠类 { public override void 打洞(string tool) //重写打洞方法 { Console.WriteLine ("new老鼠用{0}打洞",tool ); } }
overload是指重载。重载可以在一个类中定义功能类似的函数,它的优势集中体现在通过参数列表控制不同功能的实现。
重载与重写的区别:
区别:重载,函数名相同,但参数类型或个数或顺序不同;一般在同一个类中或一块代码段中;编译时多态;
重写,函数方法名、返回值类型、参数个数和参数类型 都必须相同;一般发生在存在继承关系的不同的类之间;运行时多态。
限于篇幅,这里就不举例了。
小结:继承的应用很普遍也很常用,但使用时一定要判断是否二者符合继承关系,即is-a关系。继承是一种强关系,复杂的继承会导致难以复用,所以要参考结合“合成聚合原则”使用。
多态篇。
首先理解一下什么是多态:同一操作作用于不同的对象,可以又不用的解释,产生不同的结果,这就是多态。
多态通过派生类覆写基类中的虚方法实现的。所以,真正与多态相关的不是重载和重写,而是覆写。
它分为两种类型:编译时多态和运行时多态。编译时多态通过重载实现,对于非虚成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定性实现何种操作。运行时多态是直到系统运行时,才根据实际情况觉得实现何种操作。C#中的运行时多态就是通过覆写虚成员(重写)实现。
重载与覆写区别:
重载:方法名必须相同,参数列表必须不同,返回值可以不同。
覆写:方法名、参数列表、返回值类型均必须相同。
小结:多态通过覆写和重载实现,而重载、重写、覆写三个概念之间又有很密切的联系,只有准确理解他们的含义及其之间的关系,才能真正理解多态。
总结:多态和继承是OO三大特性之二,继承是子类使用了父类的方法;多态是父类使用了子类的方法。继承实现了功能传递和延展;多态实现了单一行为的多种表示。充分利用好这两大关系,会使我们的编程之旅更富有变幻性,也为我们看待大千世界提供了更多带有思维性的新视角。