第8章继承与多态.ppt
《第8章继承与多态.ppt》由会员分享,可在线阅读,更多相关《第8章继承与多态.ppt(33页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第8章 继承与多态 本章将继续深入介绍继承和多态两个重要思想以及在本章将继续深入介绍继承和多态两个重要思想以及在C#中的实现,并详细介绍由继承和封装而衍生出的抽象类、中的实现,并详细介绍由继承和封装而衍生出的抽象类、抽象函数、密封类、密封函数、运算符重载、虚函数等重抽象函数、密封类、密封函数、运算符重载、虚函数等重要的知识点。要的知识点。章节内容章节内容8.1 继承的基础知识继承的基础知识8.2 派生类的构造函数和析构函数派生类的构造函数和析构函数 8.3 抽象类和抽象函数抽象类和抽象函数 8.4 密封类和密封方法密封类和密封方法 8.5 多态的基础知识多态的基础知识 8.6 虚方法虚方法8.
2、7 运算符重载运算符重载8.8 接口接口8.9 小结小结8.1.1 简单继承C+C+中的多重继承中的多重继承8.1.1 简单继承C为什么为什么摒弃了多继摒弃了多继承承?C#允许通允许通过多个接口过多个接口来变相地实来变相地实现有控制的现有控制的多继承多继承 8.1.2 使用继承public class Mobile /定义基类定义基类Mobile public Mobile()/基类的构造函数基类的构造函数 Console.WriteLine(I am the baseclass,Mobile.);public Mobile(string name)/基类的构造函数基类的构造函数 Consol
3、e.WriteLine(Hello,My name is +name+!);public void MemorySize(int size)Console.WriteLine(MemorySize is+size+I can store a lot.);8.1.2 使用继承public class Moto:Mobile /定义派生类定义派生类Moto public Moto()/派生类的构造函数派生类的构造函数 Console.WriteLine(I am the derivedclass,Moto.);class Program static void Main(string args)M
4、oto m=new Moto();m.MemorySize(100);Console.ReadLine();8.1.3 在派生类中使用基类的方法class CustomerAccount public decimal CalculatePrice()/实现代码实现代码 return 0.0M;class GoldAccount:CustomerAccount public decimal CalculatePrice()return base.CalculatePrice()*0.9M;8.2 派生类的构造函数和析构函数构造函数的调用顺序为,先调用基类的构造函数,构造函数的调用顺序为,先调用基
5、类的构造函数,再调用派生类中的构造函数体。再调用派生类中的构造函数体。因为基类没有不带参数的构造函数,所以即使是派因为基类没有不带参数的构造函数,所以即使是派生类的不带参数的构造函数,也必须显式调用基类生类的不带参数的构造函数,也必须显式调用基类的带参数的构造函数,尽管该参数本身毫无意义。的带参数的构造函数,尽管该参数本身毫无意义。对基类构造函数的调用必须使用对基类构造函数的调用必须使用base关键字,而不关键字,而不能像能像C+一样用具体的类名代替。一样用具体的类名代替。析构函数的调用顺序同构造函数的调用顺序完全相析构函数的调用顺序同构造函数的调用顺序完全相反。反。8.2 派生类的构造函数和
6、析构函数using System;public class Mobile string parentString;public Mobile()Console.WriteLine(Mobile Constructor.);public Mobile(string myString)parentString=myString;Console.WriteLine(parentString);public void Print()Console.WriteLine(Im a Mobile Class.);8.2 派生类的构造函数和析构函数public class Moto:Mobile public
7、 Moto():base(From Derived)Console.WriteLine(Moto Constructor.);public void Print()base.Print();Console.WriteLine(Im a Moto Class.);public static void Main()Moto moto=new Moto();moto.Print();(Mobile)moto).Print();Console.ReadLine();程序运行结果:From DerivedMoto Constructor.Im a Mobile Class.Im a Moto Class
8、.Im a Mobile Class.8.3 抽象类和抽象函数抽象类表示一种抽象的概念,用于为其派生类提供抽象类表示一种抽象的概念,用于为其派生类提供一个公共接口。抽象类由一个公共接口。抽象类由abstract修饰符声明。抽修饰符声明。抽象类只能作为其他类的基类,而不能直接实例化,象类只能作为其他类的基类,而不能直接实例化,对抽象类使用对抽象类使用new关键字会发生错误。关键字会发生错误。抽象函数没有实现代码,而是由抽象函数没有实现代码,而是由abstract修饰符声修饰符声明。抽象函数只提供函数名称,具体实现交由继承明。抽象函数只提供函数名称,具体实现交由继承的派生类。可见,抽象函数同抽象类
9、类似,也是虚的派生类。可见,抽象函数同抽象类类似,也是虚拟的,但是这里的虚拟不需要而且绝对不能使用拟的,但是这里的虚拟不需要而且绝对不能使用virtual关键字(即关键字(即abstract和和virtual修饰符不能一修饰符不能一起使用),否则会产生语法错误。起使用),否则会产生语法错误。8.3 抽象类和抽象函数抽抽象象类类可可以以包包含含抽抽象象函函数数,也也可可包包含含非非抽抽象象函函数数,而而非非抽抽象象类类不不能能包包含含抽抽象象函函数数。也也就就是是说说,包包含含了了抽抽象象函函数数的的类类一一定定是是抽抽象象类类(假假如如抽抽象象函函数数可可以以包包含含在在非非抽抽象象类类中中,
10、那那么么非非抽抽象象类类实实例例调调用用没没有有实实现现代代码码的的抽抽象象函函数数时时,显显然然不不合合理理)。当当从从抽抽象象类类派派生生非非抽抽象象类类时时,非非抽抽象象类类必必须须具具体体实实现现所所继继承承的的所所有有抽抽象象函函数数,且且必必须须使使用用override关关键键字字重重写写抽抽象象类类所所定义的函数。定义的函数。抽象类可以被抽象类所继承,结果可以仍是抽象类。抽象类可以被抽象类所继承,结果可以仍是抽象类。抽象方法被实现后,不能更改原方法的修饰符。抽象方法被实现后,不能更改原方法的修饰符。在在C+中,对抽象函数有纯虚函数一说;在中,对抽象函数有纯虚函数一说;在C#中,仅
11、使用抽中,仅使用抽象这个术语。象这个术语。8.3 抽象类和抽象函数using System;public abstract class Person public abstract void SayHello();public void About()Console.WriteLine(Abstract Demo);public class Student:Person public override void SayHello()Console.WriteLine(SayHello);8.4 密封类和密封方法当类和方法被当类和方法被sealed修饰时,就成为了密封类和密修饰时,就成为了密封类
12、和密封方法。对类来说,这表示不能继承该类;对于方封方法。对类来说,这表示不能继承该类;对于方法来说,这表示不能重写该方法。实际上,法来说,这表示不能重写该方法。实际上,Java中中也有类似的定义,但使用的关键字为也有类似的定义,但使用的关键字为final。对于密封类和密封方法的应用场合通常是商业上保对于密封类和密封方法的应用场合通常是商业上保护版权,防止被他人扩展。护版权,防止被他人扩展。8.4 密封类和密封方法class BaseClass public virtual void FinalMethod()/代码代码 class MyClass:BaseClass public sealed
13、 override void FinalMethod()/代码代码 class DerivedClass:MyClass public override void FinalMethod()/错误!错误!/代码代码 8.5 多态的基础知识多态性(多态性(Polymorphism)是一个希腊单词,指)是一个希腊单词,指“同一个名称,多种形态同一个名称,多种形态”。或者可以理解为,对同。或者可以理解为,对同一个名称,可以有不同的理解,有不同的反应。例一个名称,可以有不同的理解,有不同的反应。例如,当理发师听到如,当理发师听到“cut”的时候会开始剪头发,演的时候会开始剪头发,演员听到员听到“cut
14、”的时候会停止表演,医生听到的时候会停止表演,医生听到“cut”的时候会在病人身上进行手术。的时候会在病人身上进行手术。在面向对象编程中,多态是指调用同一个方法名,在面向对象编程中,多态是指调用同一个方法名,却执行不同的方法体。多态性是类为方法(这些方却执行不同的方法体。多态性是类为方法(这些方法以相同的名称调用)提供不同实现方式的能力。法以相同的名称调用)提供不同实现方式的能力。多态性允许对类的某个方法进行调用而无需考虑该多态性允许对类的某个方法进行调用而无需考虑该方法所提供的特定实现。方法所提供的特定实现。8.5 多态的基础知识在在C#中,多态可以分为静态多态和动态多态。中,多态可以分为静
15、态多态和动态多态。静态多态就是方法的重载(静态多态就是方法的重载(overload),也称为静),也称为静态联编,由编译器在编译期间确定真正执行方法的态联编,由编译器在编译期间确定真正执行方法的地址。方法重载和运算符重载(关于运算符重载的地址。方法重载和运算符重载(关于运算符重载的介绍可参见本章介绍可参见本章8.7节)都实现了编译时的多态性。节)都实现了编译时的多态性。对于方法重载,需要:对于方法重载,需要:方法名必须相同。方法名必须相同。参数列表必须不相同(参数个数不同、参数类型不同或参数个参数列表必须不相同(参数个数不同、参数类型不同或参数个数与类型都不相同)。数与类型都不相同)。和返回值
16、类型无关。和返回值类型无关。8.5 多态的基础知识动态多态,也称为动态联编,指的是系统在编译期动态多态,也称为动态联编,指的是系统在编译期间无法确定真正执行方法的地址,在运行期间由运间无法确定真正执行方法的地址,在运行期间由运行时(行时(Common Language Runtime,CLR)根据)根据虚方法表可动态计算出来。动态多态通过虚方法的虚方法表可动态计算出来。动态多态通过虚方法的重写(重写(override)来实现(关于虚方法的介绍可详)来实现(关于虚方法的介绍可详见本章见本章8.6节)。节)。编译时的多态性能够提供运行速度快的特点,而运编译时的多态性能够提供运行速度快的特点,而运行
17、时的多态性能够提供高度灵活和抽象的特点。行时的多态性能够提供高度灵活和抽象的特点。8.6 虚方法对于类中的方法,若声明时加上对于类中的方法,若声明时加上virtual修饰符,则修饰符,则称该方法为虚方法,否则为非虚方法。称该方法为虚方法,否则为非虚方法。和和Java不同,不同,Java中的方法默认情况下都是虚方法;中的方法默认情况下都是虚方法;C#中类的方法默认情况下都是非虚方法。中类的方法默认情况下都是非虚方法。在基类中把某个方法声明为虚方法,在派生类中就在基类中把某个方法声明为虚方法,在派生类中就可以通过在该方法名前加可以通过在该方法名前加override关键字实现对基关键字实现对基类中该
18、方法的重写类中该方法的重写 虚方法和其他一般方法有较大的区别。一般方法在虚方法和其他一般方法有较大的区别。一般方法在编译时就静态地编译到了执行文件中,其相对地址编译时就静态地编译到了执行文件中,其相对地址在程序运行期间不发生变化;而虚方法在编译期间在程序运行期间不发生变化;而虚方法在编译期间不被静态编译,它的相对地址是不确定的,会根据不被静态编译,它的相对地址是不确定的,会根据运行时期对象实例来动态判断要调用的方法。运行时期对象实例来动态判断要调用的方法。8.6 虚方法关于虚方法,需要注意:关于虚方法,需要注意:不仅仅只有方法可以虚拟,属性、事件和索引器成员都可以不仅仅只有方法可以虚拟,属性、
19、事件和索引器成员都可以虚拟,但字段不能是虚拟的。虚拟,但字段不能是虚拟的。虚成员的访问修饰符不能定义为私有。虚成员的访问修饰符不能定义为私有。使用了使用了virtual修饰符后,不允许再有修饰符后,不允许再有static、abstract或或override修饰符。修饰符。使用了使用了override修饰符后,不允许再有修饰符后,不允许再有new、static或或virtual修饰符。修饰符。在派生类中重写虚方法时,要求方法名称、返回值类型、参在派生类中重写虚方法时,要求方法名称、返回值类型、参数表中的参数个数、类型、顺序、访问修饰符都必须与基类数表中的参数个数、类型、顺序、访问修饰符都必须与
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 继承
限制150内