面向对象程序设计面向对象程序设计核心内容及案例分析课件_第1页
面向对象程序设计面向对象程序设计核心内容及案例分析课件_第2页
面向对象程序设计面向对象程序设计核心内容及案例分析课件_第3页
面向对象程序设计面向对象程序设计核心内容及案例分析课件_第4页
面向对象程序设计面向对象程序设计核心内容及案例分析课件_第5页
已阅读5页,还剩109页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

面向对象核心内容回顾及案例分析面向对象核心内容回顾及案例分析Ⅰ内容回顾Ⅰ内容回顾内容回顾列表1.继承及继承实例2.方法重写(Overwrite)3.super关键字4.方法重载(Overload)5.final修饰符6.abstract修饰符7.抽象类8.接口9.接口和抽象类对比10.接口和抽象类使用场合实例内容回顾列表1.继承及继承实例1、继承

刚开始讲继承的时候,我们就已经初始了继承的概念:子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。继承也是提高代码复用的有力手段,当多个类之间存在相同的属性和方法时,就可以考虑继承,从这些类中抽象出父类——在父类中定义这些相同的属性和方法,子类无需再定义这些相同的属性和方法,只需要通过extends语句来声明继承关系即可:继承具有单根性:即一个类只能继承最多一个类。不能出现:publicclassSonextends

Base,Base2{……}但是Base类可以继承其他类。publicclassSonextendsBase{……}son:代表子类,又叫做超类。Base:代表父类,又叫做基类。1、继承刚开始讲继承的时候,我们就已经初始了继承的概念:继继承案例分析:门

所有门都拥有开(open)和关(close)这样的动作,不管是普通的门还是安全门,所以我们这里定义一个公用的父类Door类,并且默认的认为所有的门的名字都叫门。public

classDoor{publicStringdoorName="门";//门的名字public

voidopen(){//开门方法System.out.println("门开了!");}public

voidclose(){//关门方法System.out.println("门关了");}}创建父类Door继承案例分析:门所有门都拥有开(open)和关(close创建子类——CommonDoor和SecurityDoor

public

classCommDoorextendsDoor{}普通门CommDoor:public

classSecurityDoorextendsDoor{}安全门:创建子类——CommonDoor和SecurityDoor继承测试

可以发现,在CommDoor和SecurityDoor中我们一行代码都没有写,只是继承了Door类,就可以直接使用open和close方法了。这正是继承的特点——子类可以共享父类的数据和方法。public

static

voidmain(String[]args){CommDoorcd=newCommDoor();System.out.println(cd.doorName);cd.open();cd.close();SecurityDoorsd=newSecurityDoor();System.out.println(sd.doorName);sd.open();sd.close();}结果:如果说类的数量很多,那么这种优势就更加显而易见了。但是继承的弱点是:打破了封装,当父类一旦改变,子类也就可能发生变化,类的耦合度过高,不符合我们高内聚低耦合的设计原则。继承测试可以发现,在CommDoor和SecurityDo2、方法重写(Overwrite)

方法重写(Overwrite)又叫方法覆盖(Override),是有继承关系的类之间的一种多态特性。如果,对于一般门,当调用open方的时候直接输出“门开了”就好了,可是对于安全门我们可能在开门之前需要做一个身份验证,以确定是否真的要开门。那么我们就需要在子类里面重写父类的open方法。public

voidopen(){System.out.println("/*--安全门,模拟执行了安全验证--*/");System.out.println("门开了!");}这种在子类中重新定义父类已有方法的行为就是重写,重写是多态的一种体现形式。2、方法重写(Overwrite)方法重写(Overwri3、super关键字

一般在以下情况我们会用到super关键字:1.在子类构造方法中,通过super调用父类构造方法2.在子类中访问父类被覆盖重写的方法和属性现在给Door添加构造方法,如下:publicDoor(StringdoorName){this.doorName=doorName;}在SecurityDoor中可以如下定义:publicSecurityDoor(StringdoorName,Stringbrand){super(doorName);this.brand=brand;}这里的super代表调用父类的构造方法。说明,SecurityDoor有一个自己的brand属性。3、super关键字一般在以下情况我们会用到super关键3、super关键字

如果在子类中重写了父类属性,如在Security中重新定义了doorName属性:privateStringdoorName="安全门";要想再访问到父类的属性,则可以使用:super.doorName;测试:System.out.println(this.doorName+""+super.doorName);结果:3、super关键字如果在子类中重写了父类属性,如在Sec4、方法重载(Overload)

方法重载(Overload),是类的同一功能(方法)有多种实现方式。其实重载在学习Math数学类的时候已经有所接触了,如下:这里有四个都叫max的方法,但是他们的参数列表不同,这样就可以实现,当我们不论输入任何两个数字型(double,int,float,long)的参数的时候,都能返回最大值。不需要定义doubleMax,floatMax,intMax,longMax这样的方法。4、方法重载(Overload)方法重载(Overload

假设,我们的安全门现在有多种开门方式,可以使用钥匙开门,使用6位密码开门,输入房号和访客姓名请求开门三种方式。那么我们可以做如下定义:public

void

open(Stringkey){System.out.println("/*--用钥匙开安全门,模拟验证钥匙是否正确--*/");System.out.println("门开了!");}public

void

open(int

pwd){System.out.println("/*--用6位密码开门,模拟验证密码是否正确--*/");System.out.println("门开了!");}public

void

open(int

doorNo,StringvisitName){System.out.println("/*--"+visitName+"请求"+doorNo+"开门,模拟确定是否开门--*/");System.out.println("门开了!");}不允许仅仅返回值不同的重载。如:publicvoidopen(Stringkey){……}和publicStringopen(Stringkey){……}是不能通过编译的。重载的特点:方法名都相同,参数列表不同。假设,我们的安全门现在有多种开门方式,可以使用钥匙开门,使5、final修饰符

final修饰符可以修饰类,变量,方法。被final修饰的变量叫做常量,值不能被修改,如finalintPI=3.14;被final修饰的类不能被继承。被final修饰的方法不能被重写。5、final修饰符final修饰符可以修饰类,变量,方法6、abstract修饰符

abstract修饰符可以修饰类,方法。被abstract修饰的类叫做抽象类,抽象类不能被实例化。被abstract修饰的方法叫做抽象方法,抽象方法没有方法体,不提供具体实现。public

abstract

classDoor{public

abstract

voidopen();}所谓不能实例,就是指不能:Doordoor=newDoor();所谓无方法体,不实现就是指:open方法没有具体的指定实现。那么定义这样的类和方法有什么用呢?我们最终当然要为这样的类和方法提供一个实现,这个实现就是继承他的类,他的子类可以为抽象方法提供具体的实现。抽象类通常代表一个抽象概念,可以用一句话来概括抽象类的用途:抽象类是用来继承的。反过来可以说具体类不是用来继承的,只要有可能,我们不要从具体类继承——之前我们的做法虽然实现了功能,但是没有达到思想上的真正意义。6、abstract修饰符abstract修饰符可以修饰类

使用abstract有以下几个需要遵循的原则:抽象类中可以没有抽象方法,但包含抽象方法的类就必须是抽象类。抽象方法不能是静态的。抽象类及抽象方法不能被final修饰。抽象类不象具体类那样描述一类具体事物,它是提取多种具有相似性的具体事物的共同特征而产生的。而不是一个具体描述对象的类。同时抽象类和抽象方法其实是面向契约的一种体现,抽象类就相当于一个制定者。对于某些强制要被定义和实现的方法,可以定义为抽象方法,那么一旦有子类继承该抽象类,子类就必须要按照契约来实现这个抽象方法。使用abstract有以下几个需要遵循的原则:抽象类不象具用抽象类来实现之前开关门的业务

现在我们使用抽象类来实现之前的功能。public

abstract

classDoor{public

voidopen(){System.out.println("门开了!");}public

voidclose(){System.out.println("门关了");}}这样看似在结果上没有任何变化,但是却已经符合抽象思维某种角度和语义——就相当于,水果是抽象类,那么苹果,梨就是具体类,由具体类负责来实例对象,抽象类只负责描述抽象特征和行为。注意:如果一个类继承了抽象类,但没有实现它所有的抽象方法,那么这个类也是抽象类。用抽象类来实现之前开关门的业务现在我们使用抽象类来实现之前

在Door抽象类中定义抽象方法:public

abstract

voidtheNo();如果我们现在要求每个门都必须有一个提供自己门牌号的方法——由于每个门的门牌号都不一样,所以可以定义一个抽象方法,由子类具体实现内容。在子类中实现抽象方法:public

voidtheNo(){System.out.println("我是安全门No2085");}相当于契约。实现契约。在Door抽象类中定义抽象方法:publicabstra7、接口

由于继承具有单根性,java不支持一个类有多个直接的父类,所以一个类只能继承一个抽象类。为解决这一问题,Java引入了接口类型,弥补了Java的单继承的弱点。一个类只能有一个直接的父类,但可以实现多个接口。接口的定义语法:publicinterface

接口名{

}接口只负责定义规则,不负责任何实现。实现交给实现接口的类。7、接口由于继承具有单根性,java不支持一个类有多个直接

接口有以下特点:1.接口中的成员变量默认都是publicstaticfinal的——即静态常量。2.接口中的方法都没有方法体——即可以认为都是抽象方法,但是不需要abstract关键字来修饰。3.接口不能实现接口,但可以继承多个接口。4.接口必须通过他的实现类来实例。public

interfaceUserDAO{int

DEFAULT_COLOR=1;int

RED=2;publicbooleandeleteById(intid);}定义接口:想一想,能不能在接口中定义私有的方法?接口有以下特点:publicinterfaceUser接口的实现类

实现接口:仅仅定义一个接口不去实现,就像定义一个类,但什么都不写;或者定义一个类,从来都不使用;是没有什么意义的。所以我们需要为接口编写实现类。public

classUserDAOImplimplementsUserDAO{public

booleandeleteById(intid){System.out.println("模拟通过id删除信息!");return

true;}}一个类通过implements关键字来实现一个接口,而且必须实现接口中所有的方法。习惯上,对于某个接口的实现类,我们一般命名规则是:接口名+Impl如UserDAOImpl是UserDAO接口的实现类。实现某个接口的类叫做该接口的实现类,而不是子类。接口的实现类实现接口:仅仅定义一个接口不去实现,就像定义一

一般来说,我们在实例抽象类的子类或者接口的实现类的时候,都倾向于这样的实例方法:抽象类对象名=new子类();接口对象名=new实现类();而不是直接new子类或者实现类。接口和抽象类一样不能被直接实例化,只能实例化他的实现类。这样的做法是出于多态的考虑。凡是通过这种方式实例出的对象,都可以认为他的类型就是父类或者接口类。在编写方法的时候,假如只写一个方法,将基础类作为变量或参数使用,而不是使用那些特定的衍生类,那么可以减少很多代码量。这种自下而上的抽象,就是java中所谓的“上溯造型”。一般来说,我们在实例抽象类的子类或者接口的实现类的时候,都8、抽象类和接口对比

抽象类和接口的主要区别:1.抽象类里面可以为部分方法提供实现;接口只声明方法,不提供任何实现2.一个类只能继承一个父类,但可以实现多个接口。接口是构建松耦合的软件系统的法宝,他只描述服务或者契约,没有具体的实现,可以实现解耦。所以很多大师级人物都推崇面向接口编程,而不是面向实现编程。从设计模式的角度考虑:应当优先使用对象组合,而不是类继承。那么到底什么情况下该使用接口,什么情况下使用抽象类呢?我们通过一个实例来进行考究。8、抽象类和接口对比抽象类和接口的主要区别:接口是构建松耦9、接口和抽象类使用场合实例

解决方案1.全部放进抽象类public

abstract

classDoor{public

voidopen(){System.out.println("门开了!");}public

voidclose(){System.out.println("门关了");}public

voidring(){

}}由于继承抽象类的子类可以使用父类的属性和方法。所以不管ring方法如何被定义,最终子类都是能拿到的。不符合我们只是有些门具有按门铃动作的要求。假设,我们现在有些门有开门,关门,按门铃三个动作,其中开门,关门动作是所有门都有的动作,而按门铃只是部分门才具有的,那么这三个动作该如何分配呢?9、接口和抽象类使用场合实例解决方案1.全部放进抽象类pu

解决方案2.全部放进接口这里也同样面临和抽象类一样的问题,实现接口就必须实现接口中所有的方法,违反了ISP(接口隔离原则)——不应该强迫客户程序依赖于它们不用的方法。public

interfaceDoor{

public

voidopen();

public

voidclose();

public

voidring();}那面对这样的问题,到底该怎么设计呢?解决方案2.全部放进接口这里也同样面临和抽象类一样的问题,

开门和关门动作属于门本身具有不可卸载或公有的动作,或者说本质功能。按门铃属于特殊动作,或者说附加功能。我们应当将这些不可卸载的本质功能定义在抽象类里,将附加功能定义在接口里。这样,对于有特殊功能的门只需要实现对应的功能接口就好了。//本质功能public

abstract

classDoor{public

voidopen(){

System.out.println("门开了!");

}public

voidclose(){

System.out.println("门关了");

}}//附加功能public

interfaceRingDoor{

public

voidring();}开门和关门动作属于门本身具有不可卸载或公有的动作,或者说本

普通门:安全门:public

classCommDoorextendsDoor{}public

classSecurityDoorextendsDoorimplementsRingDoor{}普通门只需要继承Door有附加功能的门可以实现对应功能的接口,即可获得该功能。这样如果我们的门还需要有报警功能,那么只需要制定一个报警接口,由具有报警功能的门来具体实现就好了。至此,对于抽象类和接口的使用场合就比较明了了。普通门:安全门:publicclassCommDoorⅡ案例1Ⅱ案例1案例1需求

为学校各中心开发这样一个小系统,包含类型:教员、中心、打印机,具体要求如下:教员、以及中心都具有方法:输出详细信息中心具有属性:打印机,能够通过中心的打印机打印教员或中心的详细信息系统要具备良好的可扩展性与可维护性打印教员中心教员

详细信息中心

详细信息detail方法(输出详细信息)案例1需求为学校各中心开发这样一个小系统,包含类型:教解决方案1

思考:这个解决方案中存在着什么问题?publicclassTeacher{//输出教员的详细信息publicStringdetail(){ return“本人是计算机老师";}}publicclassSchool{privatePrinterprinter=newPrinter();//输出中心的详细信息publicStringdetail(){return“这里是信电学院";}//使用打印机打印教员信息publicvoidprint(Teachert){printer.print(t.detail());}//使用打印机打印学院信息publicvoidprint(Schools){ printer.print(s.detail());}}publicclassPrinter{publicvoidprint(Stringcontent){System.out.println("开始打印:");System.out.println(content);}}每增加一种新类型,都需要增加相应的print(类型名称var)方法——程序的可扩展性及可维护性极差——这不符合系统的要求解决方案1思考:这个解决方案中存在着什么问题?public解决思路

可以通过多态性解决这个问题吗?显然,本系统符合使用多态性的条件教员学院detail方法(负责输出详细信息)教员

详细信息学院

详细信息1221回顾多态的含义:实现同一个接口,使用不同的实例而执行不同操作解决思路可以通过多态性解决这个问题吗?显然,本系统符合使用思考:在这个系统中,存在继承关系吗?

教员、中心属于两种不同的类型,无法通过“is-a”找到一个合适的父类教员、中心都存在一个共同的方法特征:detail,它们对detail方法有各自不同的实现——这完全符合Java接口的定义定义一个Java接口,在其中定义detail方法,但没有具体实现实现这个Java接口,不同的类对detail方法有不同的具体实现IntroduceableTeacher(教员)School(学院)思考:在这个系统中,存在继承关系吗?教员、中心解决方案2

publicinterfaceIntroduceable{publicStringdetail();}publicclassSchool

implementsIntroduceable{privatePrinterprinter=newPrinter();//输出学院的详细信息publicStringdetail(){return“这里是信电学院";}//使用学院打印机打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}publicclassTeacher

implementsIntroduceable{//输出教员的详细信息publicStringdetail(){ return“本人是软件教员";}}通过Java接口,我们同样可以享受到多态性的好处,大大提高了程序的可扩展性及可维护性使用print方法时,参数可以是任何Introduceable接口的实现类的对象,不必再为不同的类型建立不同的print方法了思考:使用了Java接口之后,这个系统有了怎样的改进?解决方案2publicinterfaceIntroduⅡ案例2Ⅱ案例2面向接口编程

什么是面向接口编程开发系统时,主体构架使用接口,接口构成系统的骨架这样就可以通过更换接口的实现类来更换系统的实现publicclassSchoolimplementsIntroduceable{privatePrinterprinter=newPrinter();publicStringdetail(){return“这里是信电学院";}//使用学院打印机打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}IntroduceableTeacher(教员)SiyuanSchool(学院)面向接口编程什么是面向接口编程开发系统时,主体构架使用接口案例2需求

升级案例1的系统,要求: 打印机有多种类型,比如:黑白打印机、彩色打印机等

学院可能配备其中任意一款打印机,负责打印教员、或者学院的详细信息 系统要具备良好的可扩展性与可维护性print方法(打印)彩色打印机黑白打印机黑白内容学院/教员详细信息彩色内容案例2需求升级案例1的系统,要求:print方法彩色打解决办法:第一步抽象出Java接口

1、分析:黑白、彩色打印机都存在一个共同的方法特征:print黑白、彩色打印机对print方法有各自不同的实现2、结论:抽象出Java接口PrinterFace,在其中定义方法print3、具体实现:publicinterfacePrinterFace{publicvoid

print(Stringcontent);}解决办法:第一步抽象出Java接口1、分析:publ解决办法:第二步实现Java接口

publicclassColorPrinter

implementsPrinterFace{publicvoid

print(Stringcontent){System.out.println("彩色打印:");System.out.println(content);}}publicclassBlackPrinter

implementsPrinterFace{publicvoid

print(Stringcontent){System.out.println("黑白打印:");System.out.println(content);}}1、分析:已经抽象出Java接口PrinterFace,并在其中定义了print方法黑白、彩色打印机对print方法有各自不同的实现2、结论:黑白、彩色打印机都实现PrinterFace接口,各自实现print方法3、具体实现:解决办法:第二步实现Java接口publicclas解决办法:第三步使用Java接口

使用Java接口1、分析:主体构架使用接口,让接口构成系统的骨架2、结论:更换实现接口的类就可以更换系统的实现3、具体实现:publicclassSchoolimplementsIntroduceable{privatePrinterFaceprinter;//打印机

publicvoidsetPrinter(PrinterFacep){this.printer=p;}publicStringdetail(){return“这里是信电学院";}publicvoidprint(Introduceableintro){

printer.print(intro.detail());}}publicclassSiyuanTest{publicstaticvoidmain(String[]args){//创建学院实例

Schoolschool=newSchool();//为该学院配备黑白打印机

school.setPrinter(newBlackPrinter());school.print(school);//为该学院配备彩色打印机

school.setPrinter(new

ColorPrinter());school.print(school);}}解决办法:第三步使用Java接口使用Java接口pubⅡ案例3Ⅱ案例3项目案例:打字游戏训练的技能点面向对象设计的思想使用类图理解类的关系类的封装构造方法的使用this、static关键字的使用项目案例:打字游戏训练的技能点任务描述需求概述根据输入速率和正确率将玩家分为不同级别级别越高,一次显示的字符数越多,玩家正确输入一次的得分也越高规定时间内完成规定次数的输入,正确率达到规定要求,则升级玩家最高级别为6级、初始级别一律为1级用户错误输入一次,游戏结束开发工具JDK6.0、Eclipse任务描述需求概述第一步:分析需要使用到的类分析本案例需要用到的类有哪些:玩家(Player)类游戏(Game)类级别(Level)类第一步:分析需要使用到的类分析本案例需要用到的类有哪些:第二步:分析各个类应该具有哪些属性玩家类(Player)的属性玩家当前级别号(levelNo)玩家当前级别积分(currScore)当前级别开始时间(startTime)当前级别已用时间(elapsedTime)游戏类(Game)级别类(Level)的属性各级别号(levelNo)各级别一次输出字符串的长度(strLength)各级别输出字符串的次数(strTime)各级别闯关的时间限制(timeLimit)各级别正确输入一次的得分(perScore)第二步:分析各个类应该具有哪些属性玩家类(Player)的属第三步:分析各个类应该具有哪些方法玩家类(Player)的方法玩游戏play()游戏类(Game)的方法StringprintStr()产生并输出字符串,返回字符串用于和玩家输入比较。voidlogic(Stringout,Stringin)比较游戏输出out和玩家输入in,根据比较结果输出相应信息第三步:分析各个类应该具有哪些方法玩家类(Player)的方第四步:审核以上设计,并优化设计修改游戏类(Game),添加属性玩家:Player添加类:LevelParampublicfinalstaticLevellevel[6]第四步:审核以上设计,并优化设计修改游戏类(Game),添加第五步:主要功能分析游戏输出字符串生成字符串、输出字符串、返回字符串生成长度固定但内容随机的字符串确认输入并输出结果输入正确、未超时输出当前级别、当前积分、已用时间计算玩家的当前级别、当前积分和已用时间玩游戏6个级别循环实现每次晋级后积分清零、计时清零第五步:主要功能分析游戏输出字符串功能流程分析游戏根据玩家的级别在控制台输出指定数量字符玩家根据控制台输出来输入相同字符,回车确认确认玩家输入是否正确如果输入错误,输出输入错误提示,游戏非正常结束如果输入正确但超时,输出玩家速度太慢提示,游戏非正常结束如果输入正确且没有超时,输出玩家的积分、级别和用时信息。继续以上操作规定时间内连续正确输入规定次数,显示升级提示;游戏重新计时计分,将一次输出更多字符。6级玩家闯关成功,输出恭喜信息,游戏正常结束功能流程分析游戏根据玩家的级别在控制台输出指定数量字符开发方案1:游戏输出字符串2:确认输入并输出结果3:玩家玩游戏4:初始化各个级别的具体参数开发方案1:游戏输出字符串1.在控制台输出随机字符串思路分析生成字符串输出字符串返回字符串难点提示Game类中的player属性,代表玩家,查询player的级别号,然后根据级别号到LevelParam类中获取该级别的字符串长度字符串长度固定可以通过for循环来实现,而随机内容可以通过获取随机数,而不同随机数对应不同字符来实现 1.在控制台输出随机字符串思路分析Game中的方法

StringBufferbuffer=newStringBuffer();Randomrandom=newRandom();//1、通过循环生成要输出的字符串for(inti=0;i<strLength;i++){ //1.1、产生随机数

intrand=random.nextInt(127); //1.2、根据随机数拼接字符串buffer.append(char(rand));}互相测试完成的程序功能测试出的缺陷记录在“常见问题列表中”单元测试StringprintStr()产生并输出字符串,返回字符串用于和玩家输入比较。Game中的方法StringBufferbuffer=2、确认用户输入并输出结果思路分析确认玩家输入是否正确如果输入不正确,则直接输出错误信息并退出程序如果输入正确如果超时,则直接输出错误信息并退出程序;如果没有超时计算玩家当前积分;计算玩家已用时间;输出玩家当前级别、当前积分、已用时间;判断用户是否已经闯过最后一关并处理2、确认用户输入并输出结果思路分析Game中的方法

longcurrentTime=System.currentTimeMillis();//如果超时if((currentTime-player.getStartTime())/1000>LevelParam.levels[player.getLevelNo()-1].getTimeLimit()){ System.out.println("你输入太慢了,已经超时,退出!"); System.exit(1);}//计算玩家当前积分player.setCurScore(player.getCurScore() +LevelParam.levels[player.getLevelNo()-1].getPerScore());voidprintResult(Stringout,Stringin)比较游戏输出out和玩家输入in,根据比较结果输出相应信息Game中的方法longcurrentTime=Sy3、玩家玩游戏思路分析创建Game对象并传入player属性;外层循环(循环次数是6,每循环一次玩家级别升一级)晋级;积分清零、计时清零;内层循环(循环次数是该级别的strTime,每循环一次完成一次人机交互)游戏输出字符串;玩家输入字符串;游戏判断玩家输入并输出相应结果。3、玩家玩游戏思路分析4、游戏开始之前初始化各个级别的具体参数信息游戏参数设置如各级别号各级别一次输出字符串的长度各级别输出字符串的次数各级别闯关的时间限制各级别正确输入一次的得分难点分析使用static修饰属性和代码块static属性属于这个类所有通过“对象名.static属性名”、“类名.static属性名”访问static方法通过“类名.static方法名”和“对象名.static方法名”访问static代码块主要作用是实现static属性的初始化当类被载入的时候执行它,且只被执行一次4、游戏开始之前初始化各个级别的具体参数信息游戏参数设置

classStaticCodeBlock{ staticStringname="defname"; static{ name="staticname"; System.out.println("executestaticcodeblock"); } publicStaticCodeBlock(){ System.out.println("executeconstructor"); }}publicclassTestStaticCodeBlock{ static{ System.out.println("executestaticcodeblockinTest"); } publicstaticvoidmain(String[]args){ System.out.println("executemain()"); newStaticCodeBlock(); newStaticCodeBlock(); newStaticCodeBlock(); }}static举例说明classStaticCodeBlock{static

publicclassLevelParam{ publicfinalstaticLevellevels[]=newLevel[6];//对应六个级别

static{ levels[0]=newLevel(1,2,10,30,1); levels[1]=newLevel(2,3,9,26,2); levels[2]=newLevel(3,4,8,22,5); levels[3]=newLevel(4,5,7,18,8); levels[4]=newLevel(5,6,6,15,10); levels[5]=newLevel(6,7,5,12,15); }}示例代码publicclassLevelParam{示例代码

讲解要点:完成情况、技能总结、经验分享、项目收获表达要求:清晰流畅、有条理、重点突出项目展示讲解要点:项目展示面向对象核心内容回顾及案例分析面向对象核心内容回顾及案例分析Ⅰ内容回顾Ⅰ内容回顾内容回顾列表1.继承及继承实例2.方法重写(Overwrite)3.super关键字4.方法重载(Overload)5.final修饰符6.abstract修饰符7.抽象类8.接口9.接口和抽象类对比10.接口和抽象类使用场合实例内容回顾列表1.继承及继承实例1、继承

刚开始讲继承的时候,我们就已经初始了继承的概念:子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。继承也是提高代码复用的有力手段,当多个类之间存在相同的属性和方法时,就可以考虑继承,从这些类中抽象出父类——在父类中定义这些相同的属性和方法,子类无需再定义这些相同的属性和方法,只需要通过extends语句来声明继承关系即可:继承具有单根性:即一个类只能继承最多一个类。不能出现:publicclassSonextends

Base,Base2{……}但是Base类可以继承其他类。publicclassSonextendsBase{……}son:代表子类,又叫做超类。Base:代表父类,又叫做基类。1、继承刚开始讲继承的时候,我们就已经初始了继承的概念:继继承案例分析:门

所有门都拥有开(open)和关(close)这样的动作,不管是普通的门还是安全门,所以我们这里定义一个公用的父类Door类,并且默认的认为所有的门的名字都叫门。public

classDoor{publicStringdoorName="门";//门的名字public

voidopen(){//开门方法System.out.println("门开了!");}public

voidclose(){//关门方法System.out.println("门关了");}}创建父类Door继承案例分析:门所有门都拥有开(open)和关(close创建子类——CommonDoor和SecurityDoor

public

classCommDoorextendsDoor{}普通门CommDoor:public

classSecurityDoorextendsDoor{}安全门:创建子类——CommonDoor和SecurityDoor继承测试

可以发现,在CommDoor和SecurityDoor中我们一行代码都没有写,只是继承了Door类,就可以直接使用open和close方法了。这正是继承的特点——子类可以共享父类的数据和方法。public

static

voidmain(String[]args){CommDoorcd=newCommDoor();System.out.println(cd.doorName);cd.open();cd.close();SecurityDoorsd=newSecurityDoor();System.out.println(sd.doorName);sd.open();sd.close();}结果:如果说类的数量很多,那么这种优势就更加显而易见了。但是继承的弱点是:打破了封装,当父类一旦改变,子类也就可能发生变化,类的耦合度过高,不符合我们高内聚低耦合的设计原则。继承测试可以发现,在CommDoor和SecurityDo2、方法重写(Overwrite)

方法重写(Overwrite)又叫方法覆盖(Override),是有继承关系的类之间的一种多态特性。如果,对于一般门,当调用open方的时候直接输出“门开了”就好了,可是对于安全门我们可能在开门之前需要做一个身份验证,以确定是否真的要开门。那么我们就需要在子类里面重写父类的open方法。public

voidopen(){System.out.println("/*--安全门,模拟执行了安全验证--*/");System.out.println("门开了!");}这种在子类中重新定义父类已有方法的行为就是重写,重写是多态的一种体现形式。2、方法重写(Overwrite)方法重写(Overwri3、super关键字

一般在以下情况我们会用到super关键字:1.在子类构造方法中,通过super调用父类构造方法2.在子类中访问父类被覆盖重写的方法和属性现在给Door添加构造方法,如下:publicDoor(StringdoorName){this.doorName=doorName;}在SecurityDoor中可以如下定义:publicSecurityDoor(StringdoorName,Stringbrand){super(doorName);this.brand=brand;}这里的super代表调用父类的构造方法。说明,SecurityDoor有一个自己的brand属性。3、super关键字一般在以下情况我们会用到super关键3、super关键字

如果在子类中重写了父类属性,如在Security中重新定义了doorName属性:privateStringdoorName="安全门";要想再访问到父类的属性,则可以使用:super.doorName;测试:System.out.println(this.doorName+""+super.doorName);结果:3、super关键字如果在子类中重写了父类属性,如在Sec4、方法重载(Overload)

方法重载(Overload),是类的同一功能(方法)有多种实现方式。其实重载在学习Math数学类的时候已经有所接触了,如下:这里有四个都叫max的方法,但是他们的参数列表不同,这样就可以实现,当我们不论输入任何两个数字型(double,int,float,long)的参数的时候,都能返回最大值。不需要定义doubleMax,floatMax,intMax,longMax这样的方法。4、方法重载(Overload)方法重载(Overload

假设,我们的安全门现在有多种开门方式,可以使用钥匙开门,使用6位密码开门,输入房号和访客姓名请求开门三种方式。那么我们可以做如下定义:public

void

open(Stringkey){System.out.println("/*--用钥匙开安全门,模拟验证钥匙是否正确--*/");System.out.println("门开了!");}public

void

open(int

pwd){System.out.println("/*--用6位密码开门,模拟验证密码是否正确--*/");System.out.println("门开了!");}public

void

open(int

doorNo,StringvisitName){System.out.println("/*--"+visitName+"请求"+doorNo+"开门,模拟确定是否开门--*/");System.out.println("门开了!");}不允许仅仅返回值不同的重载。如:publicvoidopen(Stringkey){……}和publicStringopen(Stringkey){……}是不能通过编译的。重载的特点:方法名都相同,参数列表不同。假设,我们的安全门现在有多种开门方式,可以使用钥匙开门,使5、final修饰符

final修饰符可以修饰类,变量,方法。被final修饰的变量叫做常量,值不能被修改,如finalintPI=3.14;被final修饰的类不能被继承。被final修饰的方法不能被重写。5、final修饰符final修饰符可以修饰类,变量,方法6、abstract修饰符

abstract修饰符可以修饰类,方法。被abstract修饰的类叫做抽象类,抽象类不能被实例化。被abstract修饰的方法叫做抽象方法,抽象方法没有方法体,不提供具体实现。public

abstract

classDoor{public

abstract

voidopen();}所谓不能实例,就是指不能:Doordoor=newDoor();所谓无方法体,不实现就是指:open方法没有具体的指定实现。那么定义这样的类和方法有什么用呢?我们最终当然要为这样的类和方法提供一个实现,这个实现就是继承他的类,他的子类可以为抽象方法提供具体的实现。抽象类通常代表一个抽象概念,可以用一句话来概括抽象类的用途:抽象类是用来继承的。反过来可以说具体类不是用来继承的,只要有可能,我们不要从具体类继承——之前我们的做法虽然实现了功能,但是没有达到思想上的真正意义。6、abstract修饰符abstract修饰符可以修饰类

使用abstract有以下几个需要遵循的原则:抽象类中可以没有抽象方法,但包含抽象方法的类就必须是抽象类。抽象方法不能是静态的。抽象类及抽象方法不能被final修饰。抽象类不象具体类那样描述一类具体事物,它是提取多种具有相似性的具体事物的共同特征而产生的。而不是一个具体描述对象的类。同时抽象类和抽象方法其实是面向契约的一种体现,抽象类就相当于一个制定者。对于某些强制要被定义和实现的方法,可以定义为抽象方法,那么一旦有子类继承该抽象类,子类就必须要按照契约来实现这个抽象方法。使用abstract有以下几个需要遵循的原则:抽象类不象具用抽象类来实现之前开关门的业务

现在我们使用抽象类来实现之前的功能。public

abstract

classDoor{public

voidopen(){System.out.println("门开了!");}public

voidclose(){System.out.println("门关了");}}这样看似在结果上没有任何变化,但是却已经符合抽象思维某种角度和语义——就相当于,水果是抽象类,那么苹果,梨就是具体类,由具体类负责来实例对象,抽象类只负责描述抽象特征和行为。注意:如果一个类继承了抽象类,但没有实现它所有的抽象方法,那么这个类也是抽象类。用抽象类来实现之前开关门的业务现在我们使用抽象类来实现之前

在Door抽象类中定义抽象方法:public

abstract

voidtheNo();如果我们现在要求每个门都必须有一个提供自己门牌号的方法——由于每个门的门牌号都不一样,所以可以定义一个抽象方法,由子类具体实现内容。在子类中实现抽象方法:public

voidtheNo(){System.out.println("我是安全门No2085");}相当于契约。实现契约。在Door抽象类中定义抽象方法:publicabstra7、接口

由于继承具有单根性,java不支持一个类有多个直接的父类,所以一个类只能继承一个抽象类。为解决这一问题,Java引入了接口类型,弥补了Java的单继承的弱点。一个类只能有一个直接的父类,但可以实现多个接口。接口的定义语法:publicinterface

接口名{

}接口只负责定义规则,不负责任何实现。实现交给实现接口的类。7、接口由于继承具有单根性,java不支持一个类有多个直接

接口有以下特点:1.接口中的成员变量默认都是publicstaticfinal的——即静态常量。2.接口中的方法都没有方法体——即可以认为都是抽象方法,但是不需要abstract关键字来修饰。3.接口不能实现接口,但可以继承多个接口。4.接口必须通过他的实现类来实例。public

interfaceUserDAO{int

DEFAULT_COLOR=1;int

RED=2;publicbooleandeleteById(intid);}定义接口:想一想,能不能在接口中定义私有的方法?接口有以下特点:publicinterfaceUser接口的实现类

实现接口:仅仅定义一个接口不去实现,就像定义一个类,但什么都不写;或者定义一个类,从来都不使用;是没有什么意义的。所以我们需要为接口编写实现类。public

classUserDAOImplimplementsUserDAO{public

booleandeleteById(intid){System.out.println("模拟通过id删除信息!");return

true;}}一个类通过implements关键字来实现一个接口,而且必须实现接口中所有的方法。习惯上,对于某个接口的实现类,我们一般命名规则是:接口名+Impl如UserDAOImpl是UserDAO接口的实现类。实现某个接口的类叫做该接口的实现类,而不是子类。接口的实现类实现接口:仅仅定义一个接口不去实现,就像定义一

一般来说,我们在实例抽象类的子类或者接口的实现类的时候,都倾向于这样的实例方法:抽象类对象名=new子类();接口对象名=new实现类();而不是直接new子类或者实现类。接口和抽象类一样不能被直接实例化,只能实例化他的实现类。这样的做法是出于多态的考虑。凡是通过这种方式实例出的对象,都可以认为他的类型就是父类或者接口类。在编写方法的时候,假如只写一个方法,将基础类作为变量或参数使用,而不是使用那些特定的衍生类,那么可以减少很多代码量。这种自下而上的抽象,就是java中所谓的“上溯造型”。一般来说,我们在实例抽象类的子类或者接口的实现类的时候,都8、抽象类和接口对比

抽象类和接口的主要区别:1.抽象类里面可以为部分方法提供实现;接口只声明方法,不提供任何实现2.一个类只能继承一个父类,但可以实现多个接口。接口是构建松耦合的软件系统的法宝,他只描述服务或者契约,没有具体的实现,可以实现解耦。所以很多大师级人物都推崇面向接口编程,而不是面向实现编程。从设计模式的角度考虑:应当优先使用对象组合,而不是类继承。那么到底什么情况下该使用接口,什么情况下使用抽象类呢?我们通过一个实例来进行考究。8、抽象类和接口对比抽象类和接口的主要区别:接口是构建松耦9、接口和抽象类使用场合实例

解决方案1.全部放进抽象类public

abstract

classDoor{public

voidopen(){System.out.println("门开了!");}public

voidclose(){System.out.println("门关了");}public

voidring(){

}}由于继承抽象类的子类可以使用父类的属性和方法。所以不管ring方法如何被定义,最终子类都是能拿到的。不符合我们只是有些门具有按门铃动作的要求。假设,我们现在有些门有开门,关门,按门铃三个动作,其中开门,关门动作是所有门都有的动作,而按门铃只是部分门才具有的,那么这三个动作该如何分配呢?9、接口和抽象类使用场合实例解决方案1.全部放进抽象类pu

解决方案2.全部放进接口这里也同样面临和抽象类一样的问题,实现接口就必须实现接口中所有的方法,违反了ISP(接口隔离原则)——不应该强迫客户程序依赖于它们不用的方法。public

interfaceDoor{

public

voidopen();

public

voidclose();

public

voidring();}那面对这样的问题,到底该怎么设计呢?解决方案2.全部放进接口这里也同样面临和抽象类一样的问题,

开门和关门动作属于门本身具有不可卸载或公有的动作,或者说本质功能。按门铃属于特殊动作,或者说附加功能。我们应当将这些不可卸载的本质功能定义在抽象类里,将附加功能定义在接口里。这样,对于有特殊功能的门只需要实现对应的功能接口就好了。//本质功能public

abstract

classDoor{public

voidopen(){

System.out.println("门开了!");

}public

voidclose(){

System.out.println("门关了");

}}//附加功能public

interfaceRingDoor{

public

voidring();}开门和关门动作属于门本身具有不可卸载或公有的动作,或者说本

普通门:安全门:public

classCommDoorextendsDoor{}public

classSecurityDoorextendsDoorimplementsRingDoor{}普通门只需要继承Door有附加功能的门可以实现对应功能的接口,即可获得该功能。这样如果我们的门还需要有报警功能,那么只需要制定一个报警接口,由具有报警功能的门来具体实现就好了。至此,对于抽象类和接口的使用场合就比较明了了。普通门:安全门:publicclassCommDoorⅡ案例1Ⅱ案例1案例1需求

为学校各中心开发这样一个小系统,包含类型:教员、中心、打印机,具体要求如下:教员、以及中心都具有方法:输出详细信息中心具有属性:打印机,能够通过中心的打印机打印教员或中心的详细信息系统要具备良好的可扩展性与可维护性打印教员中心教员

详细信息中心

详细信息detail方法(输出详细信息)案例1需求为学校各中心开发这样一个小系统,包含类型:教解决方案1

思考:这个解决方案中存在着什么问题?publicclassTeacher{//输出教员的详细信息publicStringdetail(){ return“本人是计算机老师";}}publicclassSchool{privatePrinterprinter=newPrinter();//输出中心的详细信息publicStringdetail(){return“这里是信电学院";}//使用打印机打印教员信息publicvoidprint(Teachert){printer.print(t.detail());}//使用打印机打印学院信息publicvoidprint(Schools){ printer.print(s.detail());}}publicclassPrinter{publicvoidprint(Stringcontent){System.out.println("开始打印:");System.out.println(content);}}每增加一种新类型,都需要增加相应的print(类型名称var)方法——程序的可扩展性及可维护性极差——这不符合系统的要求解决方案1思考:这个解决方案中存在着什么问题?public解决思路

可以通过多态性解决这个问题吗?显然,本系统符合使用多态性的条件教员学院detail方法(负责输出详细信息)教员

详细信息学院

详细信息1221回顾多态的含义:实现同一个接口,使用不同的实例而执行不同操作解决思路可以通过多态性解决这个问题吗?显然,本系统符合使用思考:在这个系统中,存在继承关系吗?

教员、中心属于两种不同的类型,无法通过“is-a”找到一个合适的父类教员、中心都存在一个共同的方法特征:detail,它们对detail方法有各自不同的实现——这完全符合Java接口的定义定义一个Java接口,在其中定义detail方法,但没有具体实现实现这个Java接口,不同的类对detail方法有不同的具体实现IntroduceableTeacher(教员)School(学院)思考:在这个系统中,存在继承关系吗?教员、中心解决方案2

publicinterfaceIntroduceable{publicStringdetail();}publicclassSchool

implementsIntroduceable{privatePrinterprinter=newPrinter();//输出学院的详细信息publicStringdetail(){return“这里是信电学院";}//使用学院打印机打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}publicclassTeacher

implementsIntroduceable{//输出教员的详细信息publicStringdetail(){ return“本人是软件教员";}}通过Java接口,我们同样可以享受到多态性的好处,大大提高了程序的可扩展性及可维护性使用print方法时,参数可以是任何Introduceable接口的实现类的对象,不必再为不同的类型建立不同的print方法了思考:使用了Java接口之后,这个系统有了怎样的改进?解决方案2publicinterfaceIntroduⅡ案例2Ⅱ案例2面向接口编程

什么是面向接口编程开发系统时,主体构架使用接口,接口构成系统的骨架这样就可以通过更换接口的实现类来更换系统的实现publicclassSchoolimplementsIntroduceable{privatePrinterprinter=newPrinter();publicStringdetail(){return“这里是信电学院";}//使用学院打印机打印信息publicvoidprint(Introduceableintro){ printer.print(intro.detail());}}IntroduceableTeacher(教员)SiyuanSchool(学院)面向接口编程什么是面向接口编程开发系统时,主体构架使用接口案例2需求

升级案例1的系统,要求: 打印机有多种类型,比如:黑白打印机、彩色打印机等

学院可能配备其中任意一款打印机,负责打印教员、或者学院的详细信息 系统要具备良好的可扩展性与可维护性print方法(打印)彩色打印机黑白打印机黑白内容学院/教员详细信息彩色内容案例2需求升级案例1的系统,要求:print方法彩色打解决办法:第一步抽象出Java接口

1、分析:黑白、彩色打印机都存在一个共同的方法特征:print黑白、彩色打印机对print方法有各自不同的实现2、结论:抽象出Java接口PrinterFace,在其中定义方法print3、具体实现:publicinterfacePrinterFace{publicvoid

print(Stringcontent);}解决办法:第一步抽象出Java接口1、分析:publ解决办法:第二步实现Java接口

publicclassColorPrinter

implementsPrinterFace{publicvoid

print(Stringcontent){System.out.println("彩色打印:");System.out.println(content);}}publicclassBlackPrinter

implementsPrinterFace{publicvoid

print(Stringcon

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论