《08 面向对象编程继承.pdf》由会员分享,可在线阅读,更多相关《08 面向对象编程继承.pdf(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 第8章 使用继承和多态 第8章 使用继承和多态 NET 在线培训学习资料 更多学习材料,请到 下载 继承是面向对象的特性之一,也是类与类之间关系的主要纽带。万物虽然复杂,但是从中找出一个本质的事物特性作为基本万物的根,这个根在类中也被称之为基类,表示其余的类都是从这个类派生出来。派生就意味着子类要从父类得到父类的所有特性,这种关系被称之为继承。本章将介绍继承的基本概念,并分析在继承中的各种方法,如 new 操作符、protected 修饰符等,还将介绍如何创建一个接口,并使用多个接口。本章也将介绍抽象类、密封类等具有特色的类形式。8.1 继承 继承指的是对被继承对象进行的一次具体化操作,因为
2、被继承的对象一般都具有一些抽象的概念,这些概念概括了很多具体的操作和概念,所以不具备可操作性,为了将对象更加实例化和明确化的目的,在继承的同时,就要将这些操作、方法和成员都进行具体化。例如,水果是一个抽象的概念,苹果就比水果更具体一些;水果具有的特性包括,气味、形状、颜色、口味等。具体到苹果,可以是带有香气的水果味道和较为圆润的外形。所以说苹果是对水果的一次具体化,也是对水果的继承,如图 9-1 所示。第 1 章 C#语言入门 213水果口味颜色形状气味水果继承水果口味颜色形状气味水果水果口味颜色形状气味水果继承 图 8-1 苹果从水果实现了继承关系 8.2 使用继承 继承体现了一种分类的方法
3、,从大量的类别中选出具有大多数基本特征的类作为可以继承的基类,而将其余能表现具体事物的类作为基类的子类,这些子类从基类中继承基类的所有特性,这种划分类的方法是对自然规律的总结,也是面向对象设计的主要特点。在本节中将分析如何实现基类和从基类派生的类,以及使用 C#语言提供的修饰符语法定义方法。8.2.1 基类和派生类 C#语言的类都来源于 System.Object 对象,也就是说所有的类都从 Object 中继承,Object 可以视为所有类的一个“根”类而存在。基类可以定义为一个基本的类,具有大多数类的一些基本特征,允许其余的类从其实现继承的操作。派生类可以定义为是一个比较复杂的类,该类从基
4、类中实现继承,具有了基类的全部特征,还可以具体实现自己独特的特征。一个典型的派生语法如下所示:Class:例如,下面的代码中首先定义了一个基类,这个基类只有一般性的特征,默认从 Object 中继承,接下来从该基类中定义一个派生类,该类实现了基类的具体操作,并且具有自己的操作。(1)打开 Visual Studio 2005 编辑器,单击“文件”菜单,选择“新建项目”命令,打开 Visual Studio2005编辑器的创建向导,接着语言选择 C#,选择“控制台应用程序”,如图 8-2 所示。第 5 章 创建 Web 窗体 214 图 8-2 类的继承的实现(2)修改生成的代码文件如下所示:u
5、sing System;using System.Collections.Generic;using System.Text;namespace jicheng class classA public classA()Console.WriteLine(基类的构造函数);public void ComputerA()/基类的成员函数 A int a,b,c;Console.WriteLine(基类的成员函数 A:);for(int i=0;i 3;+i)a=i*2;b=i+10;c=a+b;Console.WriteLine(第0次的计算过程中,+c 的值是:1,i,c);void Compu
6、terB()Console.WriteLine(这个成员不能被继承);第 1 章 C#语言入门 215 class classB:classA public classB()Console.WriteLine(从 classA 继承过来的派生类 B);public void ComputerC()int a,b,c;Console.WriteLine(n 派生类 B 的成员函数 C:);for(int i=1;i=count)transfercount-=count;Console.WriteLine(账面出错了);public float Transfercount get return t
7、ransfercount;public override string ToString()return string.Format(Bank 结余:Transfercount=0,6:C,transfercount);class Program static void Main(string args)IBank ibankcount=new BankA();ibankcount.PayIn(200);ibankcount.withdraw(100);Console.WriteLine(ibankcount.ToString();第 1 章 C#语言入门 227 (3)使用快捷键“Ctrl+
8、F5”,执行程序,如图 8-8 所示。图 8-8 接口的实现 8.3.4 接口的继承 接口与类相同,也可以实现继承,本节将进一步实现上面的程序,在此基础上实现一个继承自默认接口 IBank 的接口,并在接口实现转账的功能。(1)打开 Visual Studio 2005 编辑器,单击“文件”菜单,选择“新建项目”命令,打开 Visual Studio2005编辑器的创建向导,接着语言选择 C#,选择“控制台应用程序”,可参考如图 9-1 所示。(2)修改生成的代码文件如下所示:using System;using System.Collections.Generic;using System.
9、Text;namespace interface_jichen public interface IBank void PayIn(float count);bool withdraw(float count);float Transfercount get;public interface ITransferBankAccount:IBank bool TransferTo(IBank destination,float amount);public class CurrentAccount:ITransferBankAccount private float balance;public
10、void PayIn(float amount)balance+=amount;第 5 章 创建 Web 窗体 228 public bool withdraw(float count)if(balance=count)balance-=count;return true;Console.WriteLine(账面出错了);return false;public float Transfercount get return balance;public bool TransferTo(IBank destination,float amount)bool result;if(result=wit
11、hdraw(amount)=true)destination.PayIn(amount);return result;public override string ToString()return String.Format(当前账目结余=0,6:C,balance);public class BankA:IBank private float transfercount;public BankA()Console.WriteLine(继承自 IBank 的 BankA);public void PayIn(float count)transfercount+=count;public boo
12、l withdraw(float count)if(transfercount=count)第 1 章 C#语言入门 229 transfercount-=count;return true;Console.WriteLine(账面出错了);return false;public float Transfercount get return transfercount;public override string ToString()return string.Format(Bank 结余:Transfercount=0,6:C,transfercount);class Program sta
13、tic void Main(string args)IBank Account=new BankA();ITransferBankAccount AccountB=new CurrentAccount();Account.PayIn(200);AccountB.PayIn(500);AccountB.TransferTo(Account,100);Console.WriteLine(Account.ToString();Console.WriteLine(AccountB.ToString();(3)使用快捷键“Ctrl+F5”,执行程序,如图 8-9 所示。图 8-9 接口的继承 8.3.5
14、 ICloneable 接口 ICloneable 接口,是 C#语言提供的一种接口,该接口支持克隆,即可以使用与现有实例相同的值创建类的新实例。该接口的典型语法如下所示:ComVisibleAttribute(true)第 5 章 创建 Web 窗体 230 public interface ICloneable ICloneable 接口只有一个成员,即 Clone,该成员用于创建作为当前实例副本的新对象。在 C#语言中,有两种类型,一种是值类型,对于该类型的复制,可以直接使用深层复制的方法;对于引用类型,一般使用浅表复制的方法,这样直接将指针引用过去即可,如果要对引用类型进行深层拷贝或者
15、复制时非常麻烦,这时就需要使用到 Clone 的方法。从深层次分析,Clone 既可以作为深层副本实现,也可以作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。注意:克隆的结果必须与原始实例具有相同的类型或是原始实例的兼容类型。下面以一个实例介绍使用 Clone 的方法。(1)打开 Visual Studio 2005 编辑器,单击“文件”菜单,选择“新建项目”命令,打开 Visual Studio2005编辑器的创建向导,接着语言选择 C#,选择“控制台应用程序”,可参考如图 9-1 所示。(2)修改生成的代码文件如下所示
16、:using System;using System.Collections.Generic;using System.Text;namespace Clone class Person:ICloneable public int ID;public int age;public void Show()Console.WriteLine(ID:0 Age:1,ID,age);public object Clone()Person persons=new Person();persons.ID=this.ID;persons.age=this.age;return persons;class P
17、rogram static void Main(string args)Random rnd=new Random(unchecked(int)DateTime.Now.Ticks);Person persons=new Person4;for(int i=0;i persons.GetLength(0);i+)personsi=new Person();第 1 章 C#语言入门 231 personsi.ID=rnd.Next()%10;personsi.age=rnd.Next()%50;/打印原始数组 Console.WriteLine(打印原始数组);ShowPersons(perso
18、ns);/深拷贝 Person personsCopied=new Person4;for(int i=0;i personsCopied.GetLength(0);i+)personsCopiedi=(Person)personsi.Clone();/persons.CopyTo(personsCopied,0);Console.WriteLine(深拷贝的数组);ShowPersons(personsCopied);/浅拷贝 /*Person personsCloned=(Person)persons.Clone();Console.WriteLine(浅拷贝的数组);ShowPerson
19、s(personsCloned);*/对原数组做修改 persons2.ID+=10;Console.WriteLine(打印修改后的原始数组);ShowPersons(persons);Console.WriteLine(深拷贝的数组应该不改变);ShowPersons(personsCopied);/Console.WriteLine(浅拷贝的数组应该改变);/ShowPersons(personsCloned);public static void ShowPersons(Person persons)for(int i=0;i persons.GetLength(0);+i)perso
20、nsi.Show();(3)使用快捷键“Ctrl+F5”,执行程序,如图 8-10 所示。第 5 章 创建 Web 窗体 232 图 8-10 Clone 的使用 8.4 抽象类 在类的继承中,还有一种类型值得关注,这就是抽象类。抽象类指的是在类的定义中,只有一些无法执行的、抽象的方法,这些方法之所以无法执行的原因是抽象类不是一个完整的类,所有的方法都没有实际执行的代码。C#语言提供这样的方式,是因为抽象类往往作为一个基类进行定义,而实际的方法都会在继承的子类中进一步定义和扩充。8.4.1 抽象类的定义 抽象类的定义语法如下所示:public abstract class A /Class m
21、embers here.因为抽象类的定义,决定了其像其余的类一样实现实例化操作,这并不是说抽象类没有任何意义,其主要的作用是为多个继承的类提供共同的基类方法和定义,所以在其类中,也会出现方法的定义,只不过这些方法都是空的代码,后面以“;”结束,如下代码所示:public abstract class A public abstract void DoWork(int i);因为抽象类并没有实际执行的代码,所以所有继承的子类都要完全实现抽象类的所有方法。同样,当抽象类从基类继承虚方法时,抽象类可以使用抽象方法重写该虚方法。例如:public class D public virtual void
22、 DoWork(int i)/原来的实现.第 1 章 C#语言入门 233 public abstract class E:D public abstract override void DoWork(int i);public class F:E public override void DoWork(int i)/新的实现.8.4.2 抽象类的实例 下面以一个实例程序说明如何使用抽象类的问题。(1)打开 Visual Studio 2005 编辑器,单击“文件”菜单,选择“新建项目”命令,打开 Visual Studio2005编辑器的创建向导,接着语言选择 C#,选择“控制台应用程序”,
23、可参考如图 9-1 所示。(2)修改生成的代码文件如下所示:using System;using System.Collections.Generic;using System.Text;namespace abstract public abstract class Person public Person()Console.WriteLine(abstract 类的实例程序);public abstract void Hello();public abstract void Hello(string str);class man:Person public man()Console.Wri
24、teLine(abstract 类的子类);public override void Hello()Console.WriteLine(这个类继承了抽象类的所有属性和方法);第 5 章 创建 Web 窗体 234 public override void Hello(string str)Console.WriteLine(实现了带参数的抽象类方法);class Program static void Main(string args)man manfirst=new man();manfirst.Hello();/第二个子类 man second=new man();string str=t
25、his is second abstract type realize;second.Hello(str);(3)使用快捷键“Ctrl+F5”,执行程序,如图 8-11 所示。图 8-11 抽象类的实现 8.5 多态 通过继承的方法,一个类可以有多种用途,如可以用作自己的类型、任何的基类型,或者在实现接口时用作任何接口类型等,类的这种形式一般被称之为类的多态性。在 C#语言中,每种类型都具有多态性。每个类型都既可以用作自己的类型,也可以用作 Object 实例等,因为在 C#语言中任何类型的即类型都是 Object 类型。8.5.1 多态的定义 当派生类从基类继承时,派生类会获得基类的所有方法
26、、字段、属性和事件。若要更改基类的数据和行为,只有两种选择,一是使用新的派生成员替换基类的成员,第二种选择是重写虚拟的基类成员。使用新的派生成员替换基类的成员,这种方法需要使用 new 关键字。如果基类定义了一个方法、字段或属性,则 new 关键字用于在派生类中创建该方法、字段或属性的新定义。new 关键字放置在要替换的类成员的返回类型之前。例如:public class BaseClass 第 1 章 C#语言入门 235 public void DoWork()public int WorkField;public int WorkProperty get return 0;public
27、class DerivedClass:BaseClass public new void DoWork()public new int WorkField;public new int WorkProperty get return 0;在这个例子中,DerivedClass 类从基类中继承了基类的所有方法和成员,在继承的过程中使用了 new关键字,使得派生的类中的方法都替代了基类中的方法和成员。使用 new 关键字时,调用的是新的类成员而不是已被替换的基类成员。这些基类成员称为隐藏成员。如果将派生类的实例强制转换为基类的实例,就仍然可以调用隐藏类成员。如果不希望使用隐藏的成员,那么就需要使用
28、到 override,例如,如下代码所示:public class BaseClass public virtual void DoWork()public virtual int WorkProperty get return 0;public class DerivedClass:BaseClass public override void DoWork()public override int WorkProperty get return 0;8.5.2 多态的实例 下面以一个实例说明在多态中,如何运用 new 和 override 关键字。(1)打开 Visual Studio 20
29、05 编辑器,单击“文件”菜单,选择“新建项目”命令,打开 Visual Studio2005编辑器的创建向导,接着语言选择 C#,选择“控制台应用程序”,可参考如图 8-1 所示。(2)修改生成的代码文件如下所示:using System;第 5 章 创建 Web 窗体 236 using System.Collections.Generic;using System.Text;namespace MutilClass /定义基类 class Car public virtual void DescribeCar()System.Console.WriteLine(四个轮子+一个引擎的物体是
30、汽车.);/派生类 class ConvertibleCar:Car public new virtual void DescribeCar()base.DescribeCar();System.Console.WriteLine(汽车带有车顶蓬.);/派生类二 class Minivan:Car public override void DescribeCar()base.DescribeCar();System.Console.WriteLine(汽车最大能够载重七个人.);class Program static void Main(string args)Car cars=new Ca
31、r3;cars0=new Car();cars1=new ConvertibleCar();cars2=new Minivan();foreach(Car vehicle in cars)System.Console.WriteLine(汽车指得是:+vehicle.GetType();vehicle.DescribeCar();System.Console.WriteLine(-);第 1 章 C#语言入门 237(3)使用快捷键“Ctrl+F5”,执行程序,如图 8-12 所示。图 8-12 多态的实现 8.6 总结 本章讨论了类的两个重要概念,继承和多态。继承是类的关系中最重要的一个知识点,类的构成类似于树的形状,类与子类之间构成了枝与叶的关系,类的继承体现了唯物主义的基本思想。接口是 C#语言中一类特殊的语法形式,从形式上看,接口与类的结构较为相似。抽象类指的是在类的定义中,只有一些无法执行的、抽象的方法,这些方法之所以无法执行的原因是抽象类不是一个完整的类,所有的方法都没有实际执行的代码。多态是类体现出来的另外一个特点,为了理解类的多态性的实现,需要充分的吃透 new 和 override 关键字的用法。