《第5、6章面向对象高级应用.ppt》由会员分享,可在线阅读,更多相关《第5、6章面向对象高级应用.ppt(109页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第五章第五章 面向对象高级应用面向对象高级应用本章目标本章目标加深理解面向对象编程的概念掌握类的继承和多态以及如何实现理解接口、委托和事件以及泛型的相关概念能够综合面向对象的知识进行相关内容的设计1 继承继承“继承”这个词的字面含义是:按照法律或遵照遗嘱接受死者的财产、职务、头衔、地位等。面向对象方法中的继承与现实世界中的继承的意义基本相同,是指一个类完全继承了另一个类的所有内容,如字段、成员函数等。继承是一种父母与孩子的关系,孩子从父母那继承了一些父母的特点,并也有着与父母的不同之处。面向对象的关键特性面向对象的关键特性继承继承继承示例灯与台灯、壁灯、吊灯之间的继承关系灯灯台台灯灯壁壁灯灯吊
2、吊灯灯父类、超类、基类子类、派生类面向对象的关键特性面向对象的关键特性继承继承继承示例人与学生、教师、士兵之间的继承关系人人学学生生教教师师士士兵兵父类、超类、基类子类、派生类1.1 继承语法继承语法创建派生类语法:访问修饰符 class 类名:基类名称 类主体public public class Animalclass Animal protectedprotected bool IsSleeping;bool IsSleeping;public void Sleep()public void Sleep()public void Eat()public void Eat()public
3、class public class Lion:AnimalLion:Animal public void Prey()public void Prey().Lion adoptedLion=new Lion();Lion adoptedLion=new Lion();adoptedLion.Prey();adoptedLion.Prey();adoptedLion.Eat();adoptedLion.Eat();继承描述了“是什么种类”(is a kind of)的关系派生类从基类继承属性和方法,实现了代码重用派生类变得更专门化 父类父类子类子类动物动物大象大象猫猫 class Progra
4、m static void Main(string args)B b=new B();b.Display();Console.ReadLine();classApublicvoidDisplay()Console.WriteLine(displayina);classB:Aclass Program static void Main(string args)B b=new B();b.Display();b.T=hello;b.Dispaly11();Console.ReadLine();classApublicvoidDisplay()Console.WriteLine(displayina
5、);classB:Aprivatestringt;publicstringTgetreturnt;sett=value;publicvoidDispaly11()Console.WriteLine(值为值为0,t);1.2 在派生类中调用基类的方法在派生类中调用基类的方法在派生类中可以使用base关键字调用基类的方法。base关键字使用对象实例,所以在静态成员中使用它会产生错误。class Program static void Main(string args)Employee e=new Employee();e.GetEmployeeInfo();Console.ReadLine();c
6、lassPersonprotectedstringSchoolName=沈阳理工沈阳理工;protectedstringDep=信息系信息系;publicvoidGetInfo()Console.WriteLine(学校:学校:+SchoolName);Console.WriteLine(部门:部门:+Dep);classEmployee:PersonpublicstringEmployeeName=小红小红;publicstringzhicheng=教授教授;publicvoidGetEmployeeInfo()base.GetInfo();Console.WriteLine(员工姓名:员工
7、姓名:+EmployeeName);Console.WriteLine(员工职称:员工职称:+zhicheng);1.3 在派生类中调用基类构造函数在派生类中调用基类构造函数 在派生类中同样要以使用关键字 base 以调用基类的构造函数 public class Animal public Animal(GenderType gender)/.Console.WriteLine(Constructing Animal);public class Elephant:Animal public Elephant(GenderType gender):base(gender)/Elephant co
8、de Console.WriteLine(Constructing Elephant);public class Person int age;public Person(int age)this.age=age;public class Student:Person int age,string sex;public Student(int age,string sex):base(age)this.sex=sex;1.4 基类、派生类构造函数执行顺序基类、派生类构造函数执行顺序 在C#中,构造函数的执行顺序是:先调用基类的构造函数,再依次调用各派生类的构造函数。class Program
9、static void Main(string args)Console.WriteLine(第一次第一次实实例化,无参:例化,无参:);Child c=new Child();Console.WriteLine();Console.WriteLine(第二次第二次实实例化,有参:例化,有参:);Child c1=new Child(8);Console.ReadLine();classParentpublicParent()Console.WriteLine(基类的构造函数基类的构造函数);classChild:Parentinta;publicChild()Console.WriteLin
10、e(子类构造函数子类构造函数);publicChild(intk)a=k;Console.WriteLine(子类带参构造函数子类带参构造函数);class Program static void Main(string args)Console.WriteLine(第一次第一次实实例化,无参:例化,无参:);Child c=new Child();Console.WriteLine();Console.WriteLine(第二次第二次实实例化,有参:例化,有参:);Child c1=new Child(8);Console.ReadLine();Child c2=new Child(3,4,
11、5);classParentpublicParent()Console.WriteLine(基类的构造函数基类的构造函数);classChild:Parentinta;publicChild()Console.WriteLine(子类构造函数子类构造函数);publicChild(intk)a=k;Console.WriteLine(子类带参构造函数子类带参构造函数);publicChild(inta,intb,inc)this.a=a;MyClasstt=newMyClass(b,c);Console.Write(“子类带子类带三三参构造函数参构造函数”);classMyClassintx,
12、y;publicMyClass(intx,inty)this.x=x;this.y=y;1.5 隐藏基类方法隐藏基类方法当从基类继承一个成员时,也就继承了其执行代码。在派生类中,通过定义与基类同名的新成员可以隐藏基类成员,从而达到修改基类成员的目的修改基类成员的目的。使用new关键字显示地说明所要隐藏的成员。基类:public void Speak()派生类 new public void Speak()public class Person int age;public Person(int age)this.age=age;public void Speak()Console.writeL
13、ine(“speak language”);publicclassStudent:Personintage,stringsex;publicStudent(intage,stringsex):base(age)this.sex=sex;newpublicvoidSpeak()Console.writeLine(“speakchinese”);1.6 继承特征继承特征继承是可传递的继承是可传递的。C从B派生,B从A派生,那么C不仅继承了B中声明的成员,也继承了A中的成员。C#中的派生类只能从一个类继承。中的派生类只能从一个类继承。派生类应当是对基类的扩展。派生类应当是对基类的扩展。派生类可以添加
14、新的成员,但不能除去已经继承的成员定义类可以定义虚方法、虚属性。类可以定义虚方法、虚属性。它的派生类能够重载这些成员,从而实现类的多态性。2 多态性多态性多态性允许外界以相似的处理方式对待所有的派生类.Animal对象对象ElephantCatMouse行为行为EatGrassEatMouseEatCheese被调用的被调用的方法方法Eat()Eat()Eat()2.1 多态性定义多态性定义C#中的多态包括两类:编译时的多态性和运行时的多态性。编译时的多态性编译时的多态性是通过我们前面所介绍的方法重载方法重载来实现的。运行时的多态是指直到系统运行时,才根据实际情况决定要实现何种操作。C#中运行
15、时的多态性运行时的多态性是通过虚方法来实现的(虚方虚方法重载法重载)。2.2 虚方法重载格式虚方法重载格式public class Animal public class Animal public public virtualvirtual void void EatEat()()Console.WriteLine(Eat something);Console.WriteLine(Eat something);public class Cat:Animal public class Cat:Animal public public overrideoverride void void Eat
16、Eat()()Console.WriteLine(Eat small animals);Console.WriteLine(Eat small animals);static void Main(string args)Bicycle b=new Bicycle();b.Wheel();Tricycle t=new Tricycle();t.Wheel();Jeep j=new Jeep();j.Wheel();classVehicles/车辆车辆publicvirtualvoidWheel()Console.WriteLine(Ihave4wheels);classBicycle:Vehic
17、les/自行车自行车publicoverridevoidWheel()Console.WriteLine(Ihave2wheels);classTricycle:Vehicles/三轮车三轮车publicoverridevoidWheel()Console.WriteLine(Ihave3wheels);classJeep:Vehicles/吉普车吉普车2.3 2.3 重写重写(虚方法重载虚方法重载)与方法重载的区别与方法重载的区别重写(虚方法重载虚方法重载)发生在派生类和基类之间,要求派派生类重载方法的方法名称、方法参数类型、方法参数生类重载方法的方法名称、方法参数类型、方法参数数量、方法参
18、数顺序和方法返回值都必须与基类中的数量、方法参数顺序和方法返回值都必须与基类中的虚方法完全一样虚方法完全一样。重载是发生在一个类内部,要求方法名称相同,但参方法名称相同,但参数类型和参数个数不同。数类型和参数个数不同。2.4 虚方法总结虚方法总结虚方法重载是函数重载的一种特殊形式,在派生类重新定义虚函数时,要求方法名称,返回类型,参数个数、类型和顺序必须与基类中的虚函数完全一致。基类中若要定义虚方法,使用virtual关键字,派生类中的虚方法重载,要求声明中加上override关键字关键字。重写基类方法必须是虚拟的、抽象的或重写的(virtual,abstract,override)。思考:使
19、用多态性实现:Animal对象对象ElephantCatMouse行为行为EatGrassEatMouseEatCheese被调用的被调用的方法方法Eat()Eat()Eat()2.5 隐藏基类成员和重写方法的区别隐藏基类成员和重写方法的区别l重写方法是将代码重写,基类的代码将删除;l而隐藏基类成员并不会把基类代码删除,只是隐藏起来。l当把派生类对象转换成基类对象后,调用隐藏和重写方法时,就可以看出他们的区别:l后者是调用子类中的重写方法,而前者将还是调用基类中的方法static void Main(string args)MyDerivedClass myobj=new MyDerivedC
20、lass();MyBaseClass mybaseobj;mybaseobj=myobj;mybaseobj.DoSomething();classMyBaseClasspublicvirtualvoidDoSomething()Console.WriteLine(baseimp);classMyDerivedClass:MyBaseClasspublicoverridevoidDoSomething()Console.WriteLine(derivedimp);static void Main(string args)MyDerivedClass myobj=new MyDerivedCla
21、ss();MyBaseClass mybaseobj;mybaseobj=myobj;mybaseobj.DoSomething();classMyBaseClasspublicvirtualvoidDoSomething()Console.WriteLine(baseimp);classMyDerivedClass:MyBaseClassnewpublicvoidDoSomething()Console.WriteLine(derivedimp);2.6 隐藏基类成员和重写方法的区别。隐藏基类成员和重写方法的区别。在派生类中隐藏基类方法时,基类的此方法既可以定在派生类中隐藏基类方法时,基类的
22、此方法既可以定义为虚拟方法,也可以不定义。义为虚拟方法,也可以不定义。此时在子类中使用此时在子类中使用new来隐藏来隐藏.在派生类中重写基类方法时,基类的此方法一定要定在派生类中重写基类方法时,基类的此方法一定要定义成虚方法。义成虚方法。此时在子类中使用此时在子类中使用override来重写。来重写。3 抽象方法和抽象类抽象方法和抽象类我们在分析问题时,需要用到抽象。我们在分析问题时,需要用到抽象。比如,动物的共同特性可以定义一个动物类,但是该比如,动物的共同特性可以定义一个动物类,但是该类并不能对应一个具体的事物,只能定义一个抽象的类并不能对应一个具体的事物,只能定义一个抽象的名称,这就是名
23、称,这就是抽象类抽象类。抽象类的定义:抽象类的定义:abstractabstract修饰类的定义就表示当前类为修饰类的定义就表示当前类为一个抽象类。一个抽象类。它只能作为其它类的基类,不能实例化,所以它是一它只能作为其它类的基类,不能实例化,所以它是一种抽象的概念,用来为派生类提供一个公共接口。种抽象的概念,用来为派生类提供一个公共接口。3 抽象方法和抽象类抽象方法和抽象类此外,各种动物都有此外,各种动物都有“吃吃”的行为,我们无法给出一的行为,我们无法给出一个统一的方法。此时我们可以在他们的基类中定义一个统一的方法。此时我们可以在他们的基类中定义一个个抽象方法抽象方法,该方法什么事也不做,只
24、是定义一个抽,该方法什么事也不做,只是定义一个抽象的名字。象的名字。抽象方法抽象方法:当创建一个类时当创建一个类时,有时需要该类包含一些特有时需要该类包含一些特殊的方法殊的方法,该类对这些方法不提供实现该类对这些方法不提供实现,但是该类的非但是该类的非抽象派生类必须实现这些方法抽象派生类必须实现这些方法,这些方法称为抽象方这些方法称为抽象方法。法。3.1 抽象方法和抽象类抽象方法和抽象类抽象方法的声明格式:抽象方法的声明格式:访问修饰符访问修饰符 abstract abstract 返回值类型返回值类型 方法名(参数列表)方法名(参数列表)在派生类中必须实现抽象方法。格式为:在派生类中必须实现
25、抽象方法。格式为:访问修饰符访问修饰符 override override 返回值类型返回值类型 方法名(参数列表)方法名(参数列表)方法体方法体 3.1 抽象方法和抽象类抽象方法和抽象类抽象类的定义方式abstract class 访问级别 ()/.访问级别 abstract ();/抽象成员3.1 抽象方法和抽象类抽象方法和抽象类Public abstract class Animal public abstract void Eat();Public class Mouse:Animal public override void Eat()Console.WriteLine(“Eat c
26、heese”);static void Main(string args)Circle c=new Circle(3);Console.WriteLine(圆圆的面的面积积是:是:+c.GetArea();Rectangle r=new Rectangle(5,3);Console.WriteLine(矩形的面矩形的面积积是:是:+r.GetArea();Console.ReadLine();abstractclassShapepublicabstractdoubleGetArea();classCircle:Shapeprivatedoubler;publicCircle(doubler)t
27、his.r=r;publicoverridedoubleGetArea()returnMath.PI*r*r;classRectangle:Shapeprivatedoublel,w;publicRectangle(doublel,doublew)this.l=l;this.w=w;publicoverridedoubleGetArea()returnl*w;3.2 抽象类、抽象方法特点抽象类、抽象方法特点抽象方法是没有实现的,就连也不能有,在继承于抽象类的类中,必须使用orverride来重写抽象方法。抽象类用abstract修饰符,只能作为其他类的基类,不能被实例化,不能被密封,不能是pr
28、ivate的,也不能使用new操作符。包含抽象方法的类一定是抽象类,抽象方法只能位于抽象类中。抽象类可以包含抽象成员,也可以包含非抽象成员。4 密封类密封类sealed class表示类没有继承的必要。密封类不能作为其他类的基类。抽象类不能同时是密封的,因为抽象类总是希望被继承的。思考思考编写代码,定义一个基类MyClass,其中包含虚拟方法GetString().这个方法应返回存储在受保护字段myString中的字符串,该字段可以通过只写公共属性ContainedString来访问。从类MyClass中派生一个类MyDerivedClass.重写GetString()方法,使用该方法的基类执
29、行代码从基类中返回一个字符串,但在返回的字符串中添加文本”output from derived class”.class MyClass protected string myString;public string ContainedString set myString=value;public virtual string GetString()return myString;classMyDerivedClass:MyClasspublicoverridestringGetString()returnbase.GetString()+(outputfromderivedclass);
30、classProgramstaticvoidMain(stringargs)MyDerivedClassd=newMyDerivedClass();MyClassc=d;c.ContainedString=Console.ReadLine();Console.WriteLine(基类返回的字符串是基类返回的字符串是+c.GetString();5 接口接口接口是引用类型,一个接口的定义相当于一个约定。实现某接口的类或结构必须遵循该接口定义的约定。在某种程度上,我们可以说接口是抽象类的一种极端接口是抽象类的一种极端形式,所有的成员都不提供实现形式,所有的成员都不提供实现,仅指定实现该接口仅指定实
31、现该接口的类或结构所必须提供的成员的类或结构所必须提供的成员。注意继承接口的类必须提供接口成员的实现。接口成员包括:方法、属性、索引器、事件。C#中不支持多重继承,因此当某个类需要继承几个当某个类需要继承几个类的行为时单纯用类继承的方法不能解决,这时就要类的行为时单纯用类继承的方法不能解决,这时就要用到接口。(用到接口。(C#中允许一个接口继承多个接口)中允许一个接口继承多个接口)5.1 声明接口声明接口 声明接口声明接口:访问修饰符访问修饰符 interface 接口名:基接口接口名:基接口 /接口主体接口主体 如:如:interface IShape bool IsHungry get;s
32、et;void Eat();5.2 实现接口实现接口 要实现一个接口,必须要有类继承该接口。要实现一个接口,必须要有类继承该接口。接口的实现类可以是派生类,并且这些派生类接口的实现类可以是派生类,并且这些派生类可以包括一些自己特有的类成员。可以包括一些自己特有的类成员。5.3 接口特征接口特征接口的访问修饰符有public、protected、internal和 private。所有接口成员都隐式的具有public访问属性。在接口成员声明中不能包含任何修饰符。接口名通常以I开头。(要实现该接口,必须有类继承该接口)接口的成员不能包含常数、字段、运算符、实例构造函数、析构函数或类型,也不能包含任
33、何种类的静态成员。4545public interface IFile int delFile();void disFile();class Pragromstatic void Main()IFile objMyFile=new MyFile();objMyFile.disFile();int retValue=objMyFile.delFile();public class MyFile:IFile public int delFile()Console.WriteLine(DelFile 实现!);return 0;public void disFile()Console.WriteLi
34、ne(DisFile 实现!);运行结果:运行结果:DisFile实现!实现!DelFile实现!实现!建议:在使用建议:在使用接口成员时,接口成员时,坚持将对象转坚持将对象转换为所需的接换为所需的接口。口。46465.4 接口与继承接口与继承类无法实现多继承,即一个类只能继承于一个基类而不能同时继承于多个基类。在C#中允许一个接口继承于多个接口,当继承于多个接口时,各个接口之间用“,”号隔开。4747public class MyFile:BaseforInterface,IFile public int delFile()Console.WriteLine(DelFile 实现!实现!);
35、return 0;public void disFile()Console.WriteLine(DisFile 实现!实现!);class Programstatic void Main()IFile objMyFile=new MyFile();objMyFile.disFile();int retValue=objMyFile.delFile();objMyFile.open();运行结果:DisFile 实现!DelFile 实现!这是 BaseforInterface 的 open 方法定义一个类定义一个类:public class BaseforInterface public vo
36、id open()Console.WriteLine(“这是这是 BaseforInterface 的的open 方法方法);练习练习声明一个接口ICDPlayer,包含4个接口方法:Play:输出“play CD”Stop:输出“stop play CD”NextTrack:输出下一首,且私有字段currentTrack增1PreviousTrack:输出上一首,且私有字段currentTrack减1(currentTrack0)只读属性CurrentTrack:返回当前是第几首歌创建CDPlayer类实现该接口,模拟CD的播放、停止、下一首、上一首的操作。public interface
37、ICDPlayervoid Play();void Stop();void PreviousTrack();void NextTrack();int CurrentTrack get;public class CDPlayer:ICDPlayerprivate int currentTrack=0;public void Play()Console.WriteLine(“启动启动 CDPlayer”);public void Stop()Console.WriteLine(“停止停止 CDPlayer”);public void PreviousTrack()Console.WriteLine
38、(“向前一首向前一首”);if(currentTrack=1)currentTrack-;public void NextTrack()Console.WriteLine(“向后一首向后一首”);currentTrack+;public int CurrentTrack getreturn currentTrack;class Program static void Main()ICDPlayer cd=new CDPlayer()cd.Play();Console.WriteLine(“当前为:当前为:”+cd.CurrentTrack);cd.NextTrack();Console.Wri
39、teLine(“前进后为:前进后为:”+cd.CurrentTrack);cd.PreviousTrack();Console.WriteLine(“后退后为:后退后为:”+cd.CurrentTrack);cd.Stop();51515.5 多接口多接口C#允许多接口实现在上面的例子中,再定义一个接口,仅包含一个方法 public interface IFileTwo void applySecondInterface();5252public class MyFile:BaseforInterface,IFile,IFileTwo public int delFile()Console.W
40、riteLine(DelFile 实现!实现!););return 0;public void disFile()Console.WriteLine(DisFile 实现!实现!););public void applySecondInterface()Console.WriteLine(ApplySecondInterface 实现实现!);!);class Program static void Main()MyFile objMyFile=new MyFile();IFile file=objMyFile;file.disFile();int retValue=file.delFile(
41、);objMyFile.open();IFileTwo two=objMyFile;two.applySecondInterface();运行结果:运行结果:DisFile实现!实现!DelFile实现!实现!这是这是BaseforInterface的的open方方法法ApplySecondInterface实现实现!5.6 显示接口显示接口如果如果类类实现两个接口,并且这两个接口包含具有相同签名的成实现两个接口,并且这两个接口包含具有相同签名的成员,那么在类中实现该成员将导致两个接口都使用该成员作为员,那么在类中实现该成员将导致两个接口都使用该成员作为它们的实现。它们的实现。interfac
42、e IControl void Paint();interface ISurface void Paint();class SampleClass:IControl,ISurface public void Paint()这样的话,如果两个这样的话,如果两个接口接口成员执行不同的函数,那么这可能会成员执行不同的函数,那么这可能会导致其中一个接口的实现不正确或两个接口的实现都不正确。导致其中一个接口的实现不正确或两个接口的实现都不正确。这时可以显式地实现接口成员这时可以显式地实现接口成员 -即创建一个仅通过该接口调用即创建一个仅通过该接口调用并且特定于该接口的类成员。这是使用接口名称和一个句点命
43、并且特定于该接口的类成员。这是使用接口名称和一个句点命名该类成员来实现的。名该类成员来实现的。public class SampleClass:IControl,ISurface void IControl.Paint()System.Console.WriteLine(IControl.Paint);void ISurface.Paint()System.Console.WriteLine(ISurface.Paint);类成员类成员 IControl.Paint 只能通过只能通过 IControl 接口使用,接口使用,ISurface.Paint 只能通过只能通过 ISurface 使用。
44、两个方法实现都使用。两个方法实现都是分离的,都不可以直接在类中使用。是分离的,都不可以直接在类中使用。显式实现还用于解决两个接口分别声明具有相同名称不同成员的情况:显式实现还用于解决两个接口分别声明具有相同名称不同成员的情况:interface ILeft int P get;interface IRight int P();为了同时实现两个接口,类必须对属性为了同时实现两个接口,类必须对属性 P 和和/或方法或方法 P 使用显式实现使用显式实现以避免编译器错误。如:以避免编译器错误。如:class Middle:ILeft,IRight int ILeft.P get return 0;in
45、t IRight.P()return 0;5656public interface IFile int delFile();void disFile();public interface IFileTwo void applySecondInterface();void disFile();public class MyFile:BaseforInterface,IFile,IFileTwo.void IFile.disFile()System.Console.WriteLine(DisFile 的 IFile 实现);void IFileTwo.disFile()System.Console
46、.WriteLine(DisFile 的 IFileTwo 实现);.当两个接口中具有同名的方法时,可当两个接口中具有同名的方法时,可以使用显式接口实现以使用显式接口实现不能直接调用不能直接调用MyFile的的disFile()方法。方法。当在具体的实现类中指明接口成员所在的接口时,这种称为显式接口成员。显式接口成员没有public修饰符。interface IPartA void SetData(string data);interface IPartB:IPartA void SetData(string data);classTest:IPartBprivatestringdataA;p
47、rivatestringdataB;voidIPartA.SetData(stringdata)dataA=data;Console.WriteLine(dataA+这是调用了接口这是调用了接口A);voidIPartB.SetData(stringdata)dataB=data;Console.WriteLine(dataB+这是调用了接口这是调用了接口B);classProgramstaticvoidMain(stringargs)IPartBb=newTest();IPartAa=newTest();b.SetData(interfaceA);a.SetData(interfaceA);
48、a.SetData(interfaceB);Console.ReadKey();5.7 5.7 接口的好处和意义接口的好处和意义程序中的接口和计算机中的接口极为神似!好处是显而易见的:首先,系统扩展性大有好处。当下层派生类需要改变时,只要接口及接口功能不变,则上层基类不用做任何修改,其他派生类也不需要修改。要新增一个类,只需定义一个符合接口的类即可。另一个好处就是不同部件或层次的开发人员可以并行开工,就像制造计算机时,生产硬盘、CPU、显示器的,只要接口一致,设计合理,完全可以并行进行开发,从而提高效率。5.8 5.8 抽象类与接口的区别抽象类与接口的区别什么时候使用抽象类,什么时候使用接口,
49、是很容易模糊的概念。甚至初学者会觉得接口就是多余的,因为单从具体功能来看,除多重继承外,抽象类似乎完全能取代接口。但是,难道接口的存在仅是为了实现多重继承?抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。如果你犹豫不决时,那么可以想想你的动机是什么。抽象类和它的子类之间应该是一般和特殊的关系,而接口仅抽象类和它的子类之间应该是一般和特殊的关系,而接口仅仅是它的子类应该实现的一组规则。仅是它的子类应该实现的一组规则。例如,交通工具定义成抽象类,汽车、飞机、轮船定义成子类,可以接受的,因为汽车、飞机、轮船都是一种特殊的交通工具。当准备为组件提供多态性时
50、,表中的建议将有助于在抽象类和接口之间做出正确的选择。目标选择设计小而简练的功能块接口设计大型功能单元抽象类任务分析:任务分析:1.程序功能:模拟U盘、移动硬盘、MP3三种USB存储设备的读、写、播放音乐等操作过程,要求有很强的扩展性,可以随意增加新的设备。2.首先用类的方式类的方式实现U盘、移动硬盘、MP3三种USB存储设备,完成computer程序功能,然后增加一个新的数码相机存储设备,看看这种方式是否能实现只增加一个新的数码相机类,而不用修改computer程序?3.接着用抽象类的方式抽象类的方式实现U盘、移动硬盘、MP3三种USB存储设备,然后也增加一个新的数码相机存储设备,看看这种方