《使用C#进行面向对象编程 第八章 继承和多态.ppt》由会员分享,可在线阅读,更多相关《使用C#进行面向对象编程 第八章 继承和多态.ppt(48页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第八章第八章 继承和多态继承和多态1本章内容本章内容n继承继承n引用变量类型和所指对象类型不一致的情况引用变量类型和所指对象类型不一致的情况n多态多态n抽象类和抽象方法抽象类和抽象方法28 8.1.1 继承继承 在在C#编程语言中,通过继承可利用已有的类,编程语言中,通过继承可利用已有的类,并扩展它的属性和方法。这个已有的类可以是并扩展它的属性和方法。这个已有的类可以是.net类库中的类的或其他程序员编写的。类库中的类的或其他程序员编写的。通过继承,能够复用原有代码。通过继承,能够复用原有代码。3v什么是继承什么是继承v如何定义继承如何定义继承v子类对象的创建过程子类对象的创建过程v父类的父类
2、的private成员的继承问题成员的继承问题v 静态成员的继承问题静态成员的继承问题 v成员变量的隐藏成员变量的隐藏v方法的隐藏方法的隐藏vbase关键字关键字有关继承的知识点有关继承的知识点4 考虑如下问题考虑如下问题:定义动物,人,鱼这三个类定义动物,人,鱼这三个类存在几个问题:存在几个问题:(1)没有描述这几个类之间的关系。)没有描述这几个类之间的关系。(2)定义其他类(如猫,狗)时,除了定义该类的特殊)定义其他类(如猫,狗)时,除了定义该类的特殊属性和行为外,还需要定义动物的一般属性和行为。属性和行为外,还需要定义动物的一般属性和行为。(3)如果动物的一般属性和行为需要修改,则跟该类有
3、)如果动物的一般属性和行为需要修改,则跟该类有关的所有类的定义都需要修改。关的所有类的定义都需要修改。动物的属性动物的属性动物的行为动物的行为动物的属性动物的属性动动物的行为物的行为人的特殊属性人的特殊属性人的特殊行为人的特殊行为动动物的属性物的属性动动物的行为物的行为鱼的特殊属性鱼的特殊属性鱼的特殊行为鱼的特殊行为动物动物人人鱼鱼(1)什么是继承)什么是继承5 为解决这个问题,引入为解决这个问题,引入类的继承类的继承这个概念。这个概念。我们使得我们使得人类人类和和鱼类鱼类继承继承动物类动物类。动物的属性动物的属性动物的行为动物的行为自动具有动物类自动具有动物类的属性和行为的属性和行为人的特殊
4、属性人的特殊属性人的特殊行为人的特殊行为自动具有动物类自动具有动物类的属性和行为的属性和行为鱼的特殊属性鱼的特殊属性鱼的特殊行为鱼的特殊行为动物动物(基类(基类/父类父类/超类)超类)人人(派生类(派生类/子类)子类)鱼鱼(派生类(派生类/子类)子类)继承继承继承继承6 基类和派生类的概念是相对的,一个类既基类和派生类的概念是相对的,一个类既可以是基类,也可以是派生类。可以是基类,也可以是派生类。汽车汽车小轿车小轿车卡车卡车客车客车继承继承继承继承继承继承轮船轮船交通工具交通工具继承继承继承继承7v继承的语法形式:继承的语法形式:class 子类的名称子类的名称 :父类名称父类名称 子类特有的
5、成员变量和成员函数子类特有的成员变量和成员函数(2)如何定义继承)如何定义继承class Human:Living public void say()System.Console.Write(hello!);class Animal public int age;public void shout()8分析一所大学中的人的类层次结构分析一所大学中的人的类层次结构学生学生本科生本科生研究生研究生教师教师继承继承继承继承继承继承教职员工教职员工人人继承继承继承继承职工职工继承继承9 C#中所有的类(包括我们自己定义的类)都中所有的类(包括我们自己定义的类)都是直接或间接继承自是直接或间接继承自Sy
6、stem.Object类。类。10注意注意:(1)子类继承所有的父类成员)子类继承所有的父类成员(2)子类中能够直接访问继承自父类的)子类中能够直接访问继承自父类的public、protected成员成员(3)子类中不能够直接访问继承自父类的)子类中不能够直接访问继承自父类的private成员成员11n继承的威力继承的威力 你已经实现了一个基本的计算器程序你已经实现了一个基本的计算器程序.现在如果要你实现一个类似现在如果要你实现一个类似windows自带计算器那样既有标准版功能又有科自带计算器那样既有标准版功能又有科学版功能的计算器学版功能的计算器,你该怎么办你该怎么办?12(3)子类对象的)
7、子类对象的 创建过程创建过程n子类对象可看作内部包含着一个父类的对象子类对象可看作内部包含着一个父类的对象n子类对象的创建过程子类对象的创建过程(1)按照定义顺序初始化子类对象新定义的成员变量)按照定义顺序初始化子类对象新定义的成员变量(2)创建子类对象中包含的父类对象)创建子类对象中包含的父类对象(3)调用子类的构造函数)调用子类的构造函数class Xclass Y:X public int data;X类对象类对象Y类对象类对象data13习题:习题:下列程下列程序的输出结果序的输出结果是什么?是什么?class A public A()System.Console.WriteLine(
8、A();class B public B()System.Console.WriteLine(B();class Point public Point()System.Console.WriteLine(Point();class MapPoint:Point public MapPoint()System.Console.WriteLine(MapPoint();class ColorPoint:MapPoint public A a=new A();public B b;public ColorPoint()System.Console.WriteLine(ColorPoint();pub
9、lic static void Main()new ColorPoint();PointMapPointColorPoint14子类中不能直接访问继承自父类的子类中不能直接访问继承自父类的private成员,下列成员,下列程序编译出错程序编译出错public class A private int age=10;public class B:A public void fun()age=20;ageA类类的对象的对象ageTest类类的对象的对象继承自继承自A类类(4)父类的)父类的private成员的继承问题成员的继承问题15在子类中如何访问继承自父类的在子类中如何访问继承自父类的priva
10、te成员?成员?可以通过继承自父类的可以通过继承自父类的public或或protected成员来访问成员来访问继承自父类的继承自父类的private成员成员public class A private int age=10;public int GetAge()return age;public class B:A public void Fun()Console.WriteLine(GetAge();public class Test public static void Main(string args)B b1=new B();b1.Fun();16v 某类的静态成员为该类及该类的所有子
11、类所共有某类的静态成员为该类及该类的所有子类所共有 public class A public static int data=10;public class B:A(5)静态成员的继承问题)静态成员的继承问题17(6 6)成员变量的隐藏)成员变量的隐藏 如果子类中新定义的成员变量与父类中的某个成员如果子类中新定义的成员变量与父类中的某个成员变量同名,那么对于这个子类而言父类中的同名成员变变量同名,那么对于这个子类而言父类中的同名成员变量将被隐藏。量将被隐藏。class Living public int age=10;class Human:Living new public int age
12、=20;ageLiving类类的对象的对象ageHuman类类的对象的对象age继承自继承自Living类类Human类类新定义的新定义的成员变量成员变量18子类通过继承自父类的方法能够访问继承自父类子类通过继承自父类的方法能够访问继承自父类的被隐藏的成员变量的被隐藏的成员变量class Living public int age=10;public int getage()return age;class Human:Living public int age=20;19v静态成员变量的隐藏静态成员变量的隐藏class Living public static int age;class H
13、uman:Living new public static int age;这两个静态成员变量相互独立这两个静态成员变量相互独立20(7 7)方法的隐藏)方法的隐藏 如果子类中新定义的方法的名称、返回值类型、参如果子类中新定义的方法的名称、返回值类型、参数列表与父类中的某个方法完全相同,则称子类中的方数列表与父类中的某个方法完全相同,则称子类中的方法隐藏了父类中的方法。(注意和重载的法隐藏了父类中的方法。(注意和重载的 区别)区别)class Living public void shout()System.Console.Write(动物叫!动物叫!);class Human:Living
14、new public void shout()System.Console.Write(人叫!人叫!);21class A public void PrintNumber(int a)System.Console.WriteLine(+a);class B:A public void PrintNumber(int a,int b)System.Console.WriteLine(a);public static void Main()B b=new B();b.PrintNumber(100);习题:分析下列程序输出结果习题:分析下列程序输出结果结果:结果:10122class Point
15、public int x=0;public Point(int x)this.x=x;class MapPoint:Point public MapPoint()System.Console.WriteLine(MapPoint);public static void Main()MapPoint m1=new MapPoint();例:例:下列程序能否正常运行?下列程序能否正常运行?23class Point public int x=0;public Point(int x)this.x=x;class MapPoint:Point public MapPoint(int x)System
16、.Console.WriteLine(MapPoint);public static void Main()MapPoint m1=new MapPoint(10);例:例:下列程序能否正常运行?下列程序能否正常运行?24(8 8)basebase关键字关键字通过通过base关键字在子类中访问被隐藏的父类成员变量。关键字在子类中访问被隐藏的父类成员变量。human h1=new human();h1.changefatherdate();System.Console.WriteLine(h1.age);System.Console.WriteLine(h1.getfatherdate();cl
17、ass living public int age;class human:living new public int age;public void changefatherdate()base.age=10;public int getfatherdate()return base.age;25v注意:注意:在静态方法中不能使用在静态方法中不能使用basebase。因为通过因为通过basebase可以在子类中直接访问被可以在子类中直接访问被隐藏的父类成员,而静态成员函数可以被所隐藏的父类成员,而静态成员函数可以被所在类直接调用,并不需要创建一个对象。这在类直接调用,并不需要创建一个对象。这
18、意味着不用创建对象也可以访问类的成员,意味着不用创建对象也可以访问类的成员,这是不允许的。这是不允许的。26在子类中可以通过在子类中可以通过base关键字,调用父类的构造函关键字,调用父类的构造函数以初始化子类对象中继承自父类的成员变量。数以初始化子类对象中继承自父类的成员变量。class Point public int x=0;public Point(int x)this.x=x;System.Console.WriteLine(Point);class MapPoint:Point public MapPoint():base(10)System.Console.WriteLine(M
19、apPoint);public static void Main()MapPoint m1=new MapPoint();System.Console.WriteLine(m1.x);278 8.2.2 引用变量类型与所指对象类型不一致引用变量类型与所指对象类型不一致class Livingpublic int age;public void Eat()System.Console.WriteLine(吃吃);class Human:Living public int money;public void Read()System.Console.WriteLine(看书看书);28v(1)父类
20、引用指向子类对象。)父类引用指向子类对象。Living l1=new Human();当父类引用指向子类对象时,父类引用实际指向的是子类当父类引用指向子类对象时,父类引用实际指向的是子类对象中隐含的父类对象。因而父类引用只能访问子类对象中继对象中隐含的父类对象。因而父类引用只能访问子类对象中继承自父类的成员。承自父类的成员。l1new产生的产生的Human对象对象moneyRead()隐含的隐含的Living类对象类对象ageeat()29l1.Eat();/正确正确System.Console.WriteLine(l1.age);/正确正确l1.Read();/错误错误(Human)l1).
21、Read();/正确,对正确,对l1进行强制类型转换可使其调进行强制类型转换可使其调用用Read()子类引用可以赋给父类引用子类引用可以赋给父类引用Human h1=new Human();Living l1=h1;/正确正确l1new产生的产生的Human对象对象moneyRead()隐含的隐含的Living类对象类对象ageEat()30(2)子类引用不能指向父类对象。)子类引用不能指向父类对象。Human h1=new Living();/错误错误v父类引用一般不能直接赋给子类引用。父类引用一般不能直接赋给子类引用。Living l1=new Living();Human h1=l1;/
22、错误错误v如果某个父类引用指向的是一个子类对象,那么这个父如果某个父类引用指向的是一个子类对象,那么这个父类引用可以赋给子类引用,而且要用强制类型转换类引用可以赋给子类引用,而且要用强制类型转换Living l1=new Human();Human h1=(Human)l1;h1.Read();31class A public string s=A;class B:A new public string s=B;class test public static void Main()A a1=new B();B b1=(B)a1;System.Console.WriteLine(b1.s);B
23、 b2=new B();A a2=b2;A a3=b2;System.Console.WriteLine(a2.s);System.Console.WriteLine(B)a3).s);习题:下列程序的输出结果?习题:下列程序的输出结果?输出结果:输出结果:B BA AB B32v多态的概念多态的概念v使用虚函数实现动态多态使用虚函数实现动态多态8 8.3.3 多态多态33多态可理解为多态可理解为“一个接口,多个实现一个接口,多个实现”多态将接口与实现分离多态将接口与实现分离.多态多态提高了系统的可扩展性提高了系统的可扩展性多态多态使得代码的组织及可读性获得改善。使得代码的组织及可读性获得改善
24、。(1)多态的概念)多态的概念34静态多态静态多态(方法的重载方法的重载)动态多态动态多态35(1)子类)子类重写(重写(override)父类的父类的虚方法虚方法(2)父类引用指向子类对象)父类引用指向子类对象(3)父类引用调用被重写的方法)父类引用调用被重写的方法(2)动态多态的语法要求)动态多态的语法要求36class A public virtual void fun()System.Console.Write(A);class B:A public override void fun()System.Console.Write(B);class Test public static
25、void Main()A a1=new B();a1.fun();a1.fun()按理说应调用按理说应调用a1所指对所指对象继承自父类的方法,但由于有象继承自父类的方法,但由于有多态,情况发生变化。多态,情况发生变化。37n动态多态的作用动态多态的作用38多态的例子。多态的例子。class Person public void Drive(Car c)c.run();class test public static void Main()Person p1=new Person();Xiali x1=new Xiali();p1.Drive(x1);Benz b1=new Benz();p1.
26、Drive(b1);System.Console.ReadLine();class Car public virtual void run()class Xiali:Car public override void run()System.Console.Write(夏利车在行驶夏利车在行驶);class Benz:Car public override void run()System.Console.Write(奔驰车在行驶奔驰车在行驶);398 8.4.4 抽象类和抽象方法抽象类和抽象方法 使用多态的时候,有时我们并不需要创建父类对象,而使用多态的时候,有时我们并不需要创建父类对象,而且
27、父类中的某些方法不需要方法体,这时可以使用且父类中的某些方法不需要方法体,这时可以使用抽象类和抽象类和抽象方法抽象方法。不含方法体的方法就是不含方法体的方法就是抽象方法抽象方法,它的方法体的实现交,它的方法体的实现交给该类的子类根据自己的情况去实现。给该类的子类根据自己的情况去实现。/一个抽象方法一个抽象方法 public abstract void fun();包含抽象方法的类就叫包含抽象方法的类就叫抽象类抽象类。abstract class A public abstract void fun();40v 在抽象类中,并不是所有的方法都是抽象方法。在抽象类中,并不是所有的方法都是抽象方法。
28、但只要有一个,该类就必须定义为抽象类。但只要有一个,该类就必须定义为抽象类。class A public abstract void fun();错误错误abstract class A public void fun()System.Console.WriteLine(hello);v 抽象类中也可以不包含抽象方法。抽象类中也可以不包含抽象方法。正确正确41v抽象类不能创建任何对象。抽象类不能创建任何对象。abstract class A public void fun()System.out.println(hello);A a1=new A();/编译错误编译错误 42v如果抽象类有抽象
29、方法,则所有的抽象方法在子类中如果抽象类有抽象方法,则所有的抽象方法在子类中要被实现,否则子类仍是抽象的,不能创建对象。要被实现,否则子类仍是抽象的,不能创建对象。abstract class A public abstract void fun();class B:A/编译错误,子类也要加上编译错误,子类也要加上abstract 43abstract class Shape public abstract void draw();/上述方法对一般图形无法定义其实现上述方法对一般图形无法定义其实现 class Rectangle :Shape int width;int length;publ
30、ic override void draw()/矩型类实现了方法矩型类实现了方法draw()Shape s=new Rectangle();s.draw();一个抽象类的例子一个抽象类的例子448 8.5.5 接口接口 接口是一种特殊的抽象类。接口中不能包含成员变量,接接口是一种特殊的抽象类。接口中不能包含成员变量,接口中所有成员默认具有口中所有成员默认具有public和和abstract修饰符。修饰符。接口的定义:接口的定义:访问权限访问权限 interface 接口名接口名:基接口列表基接口列表 方法声明方法声明 interface Shape void draw();45class Re
31、ctangle :Shape int width;int length;public void draw()System.Console.WriteLine(画矩形);接口的实现接口的实现46 接口可以作为一种引用类型来使用。任何实现该接口的类接口可以作为一种引用类型来使用。任何实现该接口的类的对象都可以被该接口类型的引用变量所指向。通过这些引用的对象都可以被该接口类型的引用变量所指向。通过这些引用变量可以访问类所实现的接口中的方法。变量可以访问类所实现的接口中的方法。例如,例如,Rectangle类实现了类实现了Shape接口,可以如下赋值,和父接口,可以如下赋值,和父类引用指向子类对象是类
32、似的:类引用指向子类对象是类似的:Shape s=new Rectangle();接口类型的引用接口类型的引用实现该接口的类实现该接口的类的对象的对象47 interface Shape void draw();class Rectangle :Shape int width;int length;public void draw()System.Console.WriteLine(画矩画矩形形);class test public static void Main()Shape s=new Rectangle();s.draw();System.Console.ReadLine();接口实现多态的例子接口实现多态的例子48