十.多态用抽象类与接口实现多态一.抽象类(AbstractClass)•在Java中定义类时,可以仅声明方法名称而不写任何代码,这样的方法称为抽象方法.如果一个类中包括了抽象方法,则该类称之为抽象类.1.1抽象类不能构造对象•抽象类是拥有未完成方法的类,所以它不能用来生成对象,它只能被继承扩展,并在子类中完成未完成的抽象方法.1.2声明抽象方法与抽象类•在Java中声明抽象方法与抽象类,要使用abstract关键词.•格式:•abstractclass类名称{•publicabstract返回值类型方法名称();•}例题解析-多态导论•//实心圆•classShiXinYuan{•privatedoublebanjing;•publicvoidsetBanjing(doublebanjing){•this.banjing=banjing;•}•publicdoublegetBanjing(){•returnbanjing;•}•publicvoidHuaYuan(){•System.out.println(画一个半径是+banjing+的实心圆);•}•}例题解析-多态导论•//空心圆•classKongXinYuan{•privatedoublebanjing;•publicvoidsetBanjing(doublebanjing){•this.banjing=banjing;•}•publicdoublegetBanjing(){•returnbanjing;•}•publicvoidHuaYuan(){•System.out.println(画一个半径是+banjing+的空心心圆);•}•}代码分析•这两个类除了HuaYuan()的方法实现内容不同之外,其他的定义是一样的.而且这两个类所定义的都是圆的一种类型.•可以定义个抽象类Yuan,将ShiXinYuan与KongXinYuan中相同的行为与定义提取到抽象类中实心圆与空心圆的抽象类•abstractclassYuan{•protecteddoublebanjing;•publicvoidsetBanjing(doublebanjing){•this.banjing=banjing;•}•publicdoublegetBanjing(){•returnbanjing;•}•publicabstractvoidHuaYuan();//抽象方法•}重申一遍,在声明Yuan这个类的时候使用了abstract关键字,它是抽象类,它只能被继承,而HuaYuan的方法使用了abstract关键字,它是抽象方法,谁继承这个抽象类就必须要完成这个抽象方法扩展抽象类-空心圆•classKXYextendsYuan{•publicvoidHuaYuan(){•System.out.println(画一个半径是+this.banjing+的空心圆);•}•}扩展抽象类-实心圆•classSXYextendsYuan{•publicvoidHuaYuan(){•System.out.println(画一个半径是+this.banjing+的实心圆);•}•}抽象导论:实例2实例1实心圆操作界面空心圆操作界面调用一个接口实现两个实例的操作实现多态•publicclassAbstractDemo{•publicstaticvoidHuaYuan(Yuany){•y.HuaYuan();•}•publicstaticvoidmain(String[]args){•//TODO自动生成方法存根•HuaYuan(newKXY());•HuaYuan(newSXY());•}•}结论:•从上面的图中,多态实现所指的,使用同一个实现接口,以实现不同的对象实例。•由于共同的定义被提取到了抽象类中,所以在实现空心圆与实心圆的类中不用重复定义,只要定义个别的画圆方法就可以了,由于空心圆与实心圆都是抽象类圆的子类,因而可以使用抽象类上有定义的实现接口,来实现子类实例上的方法.二.抽象类的应用•为了加深对抽象类的了解与应用方式,再来举一个例子说明抽象类。•下面的例子中定义了一个简单的比数字大小游戏的抽象类.猜数字的抽象类•abstractclassCaiShu{•privateintnumber;•publicvoidsetNumber(intnumber){this.number=number;}•publicvoidstart(){•showMessage(欢迎);•intguess=getUserInput();•do{•if(guessnumber){•showMessage(输入的数字较大);•}•elseif(guessnumber){•showMessage(输入的数字较小);•}•else{•showMessage(猜中了);•}•}while(guess!=number);•}•protectedabstractvoidshowMessage(Stringmessage);•protectedabstractintgetUserInput();•}这是一个抽象类,在类中定义了start()方法,其中先实现比大小游戏的基本规则,然而并不实现如何取得用户输入信息的显示方式,只先定义了抽象方法showMessage()与getUserInput()。继承抽象类制作游戏类•classTextModeGameextendsCaiShu{•privateScanners;•publicTextModeGame(){•s=newScanner(System.in);•}•protectedvoidshowMessage(Stringmessage){•for(inti=0;imessage.length();i++){•System.out.print(**);•}•System.out.println(\n+message);•for(inti=0;imessage.length();i++){•System.out.print(**);•}•}•protectedintgetUserInput(){•System.out.println(\n输入数字:);•returns.nextInt();•}•}测试•publicclassCaiShuZi{•publicstaticvoidmain(String[]args){•CaiShuguessGame=newTextModeGame();/*重点*/•guessGame.setNumber(50);•guessGame.start();•}•}遥控器numbersetNumberstart()showMessagegetUserInput抽象类CaiShuint变量方法方法抽象方法抽象方法setNumberstart()showMessagegetUserInputTextModeGameint变量方法方法方法方法Scanner多态:父类引用指向子类对象。父类只能调用父类中所拥有的方法.抽象类实现多态的方式三.接口(Interface)•表面上看,接口有点像是完全没有任何方法被实现的抽象类.3.1抽象类与接口的区别•但实际上两者在语义与应用上是有差别的。“继承某抽象类的类必须是该抽象类的一个子类,由于同属一个类型”只要父类中有定义同名方法,就可以通过父类类型来实现子类实例中被重写的方法,也就是通过父类类型进行多态实现,但“实现某接口的类并不归属于哪一类”,一个对象上可以实现多个接口.3.2定义接口的格式:•interface接口名称{•封装等级返回值类型方法名称(参数列);•封装等级返回值类型方法名称(参数列);•}•//在声明接口时方法上权限设置可以省略不写,如果省略的话,默认是public.•interfaceIRequest{•publicvoidexecute();•}3.3用类实现接口内容•格式:•class类名称implements接口1,接口2{•//实现接口内容•}•在定义类时,可以使用implements关键字来指定实现哪个接口,注意的是接口中所有定义的方法都要实现.用HelloRequest实现接口•classHelloIRequestimplementsIRequest{•privateStringname;•publicHelloIRequest(Stringname){•//TODO自动生成构造函数存根•this.name=name;•}•publicvoidexecute(){•//TODO自动生成方法存根•System.out.println(您好+name);•}••}用WelcomRequest实现接口•classWelcomeRequestimplementsIRequest{•privateStringplace;•publicWelcomeRequest(Stringplace){•this.place=place;•}•publicvoidexecute(){•//TODO自动生成方法存根•System.out.println(欢迎您来到+place);•}•}多态导论•*虽然HelloRequest与WelcomeRequest是两种不同的类型类,但它们都实现了IRequest接口,所以我们做个方法只要知道IRequest定义了什么方法,就可以实现HelloRequest与WelcomeRequest的实例,而不用知道传入的对象到底是什么类的实例.接口execute()IRequest接口execute()nameHelloIRequestexecute()placeWelcomeRequest接口实现多态导论接口实现多态•publicclassInterfaceDemo{•publicstaticvoidmain(String[]args){•HelloIRequesth1=newHelloIRequest(IBM);•WelcomeRequestw1=newWelcomeRequest(SSZ);•doRequest(h1);•doRequest(w1);•}•publicstaticvoiddoRequest(IRequestrequest){•request.execute();•}•}3.4实现多个接口与接口继承•3.41当实现多个接口时,记得必须实现每一个接口中所定义的方法。•3.42接口继承格式:•interface名称extends接口1,接口2{•}•不同于类依次只能继承一个父类,一个接口可以同时继承多个接口,实现子接口的类必须将所有在父接口与子接口中定义的方法全部实现.•//惯例,在给接口起名称的时候最好在前面加上大些字母I