第九天面向对象4今日任务:1、抽象类:i.了解抽象类的特点ii.掌握抽象类的细节和应用2、多态:i.了解多态的概念和在代码中的体现ii.了解多态的好处、弊端和前提iii.掌握多态中的转型iv.掌握多态中成员的使用细节v.多态练习:代码课后一定要多练习几遍3、接口:i.理解接口的概念、特点和作用;ii.掌握接口的使用思想iii.理解抽象类和接口的区别4、适配器设计模式i.理解适配器模式的思想以及它能解决的问题ii.理解接口的适配1.final关键字有的时候不想别人重写我的方法;使用final关键字修饰该方法;final:最后的,最终的;可以修饰类、修饰函数、修饰变量;修饰类:该类不能被继承;直接写在class关键字前面修饰函数:函数不能被重写;直接写在函数返回值类型前面;修饰变量:变量的值不能被修改,可以成为常量;直接写在变量的数据类型前面;因为被final修饰的变量的值不能改变,所以被fianl修饰的变量有叫做常量;此时,我们给他的命名的书写规范:全部字母都要大写;多个单词,可以使用下划线(_)分开;如:privatestaticfinaldoublePI=3.14;变量的值不能改变,指的是直接保存在变量中的内容不能改变;如果被final修饰的变量是一个引用类型的数据,那么通过这个引用改变堆空间中的数据,不会报错;如果试图改变变量中保存的引用地址,这时候就该报错了;2.抽象类2.1.抽象类的产生需求:创建类描述猫和狗的行为;猫的行为:抓老鼠;吃鱼;狗的行为:看家;吃骨头;分析:因为猫和狗都是动物,所以可以让猫和狗分别继承动物类,然后将共同东西抽取到动物类中;小结:当事物的功能描述不清,只能表示有这个功能时,就应该使用抽象修饰该功能,这个功能就是抽象的功能;如果一个类中有抽象的功能,那么这个类也是抽象的类;2.2.抽象的特点2.2.1.抽象类不能实例化因为抽象类,表示一个描述不清的事物,所以不能实例化;2.2.2.子类继承抽象类,必须实现父类的所有抽象函数,否则子类也是抽象的抽象类,必须由子类去继承,继承的子类必须实现父类中所有的抽象方法;2.2.3.抽象函数必须放在抽象类中因为类中有抽象函数,表示描述不清的功能,所以整个类所描述的事物,也是描述不清的,所以需要将类也定义为抽象的;2.3.抽象类的细节问题1,抽象类一定是父类吗?是,因为抽象类就是通过不同的子类向上抽取共性信息得倒的;抽线类必须由子类去继承和重写抽象函数;2,抽象类中有构造方法吗?必须有,因为抽象类需要由子类去继承,子类实例化的时候,要调用父类的构造函数;抽象类的构造函数作用是初始化本类中的成员变量的;3,抽象类中可以不书写抽象方法吗?可以;可以只有非抽象的成员;同样,不能实例化;4,抽象类中可以定义非抽象的方法吗?(抽象类中可以书写普通方法和成员变量)抽象类中除了抽象函数,还可以定义所有一般类中可以定义的成员;5,抽象关键字abstract不能和哪些修饰符关键字共存?因为抽象的函数只有被继承的子类重写了,才可以使用,所以不能和private以及final关键字一起使用;static:因为静态的函数可以直接使用类名调用,所以也不能使用static修饰抽象函数;6、抽象类什么时候使用?当描述的功能不确定,不知道具体怎么实现的时候,就需要使用抽象函数,这是类也是抽象的;不想实例化这个类(包括自己也不行),但是允许别人继承,也可以使用抽象类;2.4.抽象类的应用需求:描述Hr和程序员:有共同的3.多态3.1.多态的引入狗;哈士奇;二哈;动物;生物;汪星人;畜生……生活中的一个实实在在的事物,我们可以使用不同的状态去描述;这就是多态;而且我们在生活中,我们更习惯使用抽象的、一般化的概念来描述一个具体的事物;酒:啤酒;白酒;黄酒;红酒……饭:米饭;面条;饺子;包子……使用一般化、抽象化的概念指代一个具体的事物,就是多态在生活中的体现;3.2.java中的多态3.2.1.多态的体现上面代码中红框部分使用了多态;结论:在java中,多态,指的是父类型引用指向子类实例对象;(接口类型引用指向实现类对象)3.2.2.多态的使用前提生活中的前提:被指代的事物确实是用于描述它的那个概念的一个特例;Java中的前提:必须是继承关系(或者接口实现关系);3.2.3.多态的好处生活中:使用多态指代事物,能够指代的范围更广泛,到了实际操作的时候,就有更多的选择;Java中的好处:描述猫和狗的行为,同时需要提供测试方法;首先描述和测试猫接下来描述和测试狗的行为问题:每添加一个被测试的类型的对象,都需要单独创建一个专门的功能,而且在这些测试功能中,实现是类似的;问题就是,代码复用性差,程序扩展性差;解决:考虑使用多态,直接创建一个测试父类型的方法,然后就可以接受不同类型的对象;/*描述猫和狗的行为,同时需要提供测试方法;*///描述动物abstractclassAnimal{abstractvoideat();abstractvoidsleep();}//描述猫的行为classCatextendsAnimal{//吃voideat(){System.out.println(吃鱼);}//睡觉voidsleep(){System.out.println(猫咪睡着了);}}//描述狗的行为classDogextendsAnimal{//吃voideat(){System.out.println(吃骨头);}//睡觉voidsleep(){System.out.println(狗狗睡着了);}}//创建测试类测试classTest2{//测试动物的行为publicstaticvoidtestAnimal(Animalanimal){animal.eat();animal.sleep();}publicstaticvoidmain(String[]args){//使用多态指向猫的对象Animalcat=newCat();testAnimal(cat);//使用多态指向狗的对象Animaldog=newDog();testAnimal(dog);}}另中写法:小结:使用多态,可以提高程序的扩展性,降低代码的冗余;3.2.4.多态的弊端使用父类型引用指向子类对象,不能通过父类性引用访问子类特有属性和行为;3.3.多态的类型转换3.3.1.多态的类型转换自动向上转型:将子类性对象赋值给父类型引用,可以自动进行;提升了子类对象的类型;强制向下转型:将父类型引用转为子类性引用,降低了引用的类型,需要强制转换;结论:是用强制向下转型,可以解决多态使用的弊端;3.3.2.强制向下转型的问题3.3.3.instanceof关键字instanceof:比较运算符;运算符左边是一个指向一个对象的引用(左边就是一个变量名),右边是一个类名,运算符表示的意思就是:判断左边的对象的类型是不是右边的类;结论:使用instanceof关键字,可以实时判断一个对象的类型,就可以避免强制类型转换中容易出现的类型转换异常;3.4.多态中成员的特点程序分为编译和运行两个阶段,程序中的成员,又分为静态和非静态两种,所以,要分不同情况讨论;在使用多态的程序中,编译时,不管是什么成员,编译器都看的是父类型的引用;在运行时,所有成员变量都是用的是父类型的;静态函数使用的是父类型的,非静态函数使用的是子类重写的;总结:在使用多态时,成员的特点:编译期:不管什么成员,只要用到了,都要检查父类中有没有;运行期:所有成员变量和静态函数都是使用的父类的,非静态函数使用的是子类重写的;静态成员不参与多态,只有非静态成员才与多态,因为多态是和对象有关的;编译时都要看等号左边;运行时,只有非静态函数看等号右边;3.5.多态练习需求:描述老板让Hr、程序员干活;/*需求:描述老板让Hr、程序员干活;*///描述HrclassHr{voidwork(){System.out.println(人事管理);}}//描述程序员classProgrammer{voidwork(){System.out.println(敲代码改变世界!);}}//描述老板classBoss{//老板让Hr干活voidletHrWork(Hrhr){hr.work();}//老板让程序员干活voidletProWork(Programmerpro){pro.work();}}classTest5{publicstaticvoidmain(String[]args){Bossboss=newBoss();Hrhr=newHr();boss.letHrWork(hr);Programmerpro=newProgrammer();boss.letProWork(pro);}}传统的做法,太麻烦,需要一个一个去做;而实际生活中不是这样,老板一个命令,所有干活的都要去工作,所以考虑从使用多态解决://描述打工的abstractclassWorker{abstractvoidwork();}//描述HrclassHrextendsWorker{voidwork(){System.out.println(人事管理);}}//描述程序员classProgrammerextendsWorker{voidwork(){System.out.println(敲代码改变世界!);}}//描述老板classBoss{voidletWorkerWork(Workerworker){worker.work();}}classTest6{publicstaticvoidmain(String[]args){Bossboss=newBoss();Workerhr=newHr();boss.letWorkerWork(hr);Workerpro=newProgrammer();boss.letWorkerWork(pro);}}多态总结:概念:一种事物可以有多种表示形态;而且一般习惯使用更抽象、更一般化的形态表示这个事物;多态在Java中的体现:父类型引用指向子类实例对象;接口引用指向实现类对象;多态的前提:必须有继承或者接口实现的关系;多态的好处:提高代码的复用性,提高程序的扩展性;多态的弊端:不能使用子类对象特有的属性和功能;解决多态弊端的方法:使用强制类型转换;使用强制类型转换容易出现类型转换异常,解决的办法是转换前使用比较运算符:instanceof判断;多态使用中成员的特点:编译时,所有成员都看父类;运行时,只有非静态成员函数看子类;静态成员不参与多态;4.接口4.1.接口的引入需求:分别描述以下三种动物的行为:狗:吃;叫;猫:吃;叫;猪:吃;叫;接下来,需求升级:狗和猫经过训练,都学会了表演;4.2.接口的代码体现:4.2.1.接口的声明格式:接口使用关键字:interface声明;4.2.2.接口中能书写的成员:接口和类不同,在接口中可以书写的内容,都已经被Java固定了:成员变量:只能使用一下修饰符:publicstaticfinal;也就是说,接口中的成员变量,都是常量;成员函数:只能使用修饰符:publicabstract;也就是说,接口中的方法,都是公共和抽象的;这些修饰符,是Java在语法层面固定的,我们可以省略不写,编译器会帮我们加上;要写,就只能这么写,不能改写;一般函数前面的修饰符,推荐public不要省略;4.2.3.接口的实现:接口和抽象类一样,都无法实例化;需要使用一个类来实现接口,使用关键字:implements4.2.4.多态使用接口:一般开发中,都会通过多态的方式使用接口;接口类型的引用指向实现类的对象;4.3.接口的多实现&多继承接口的多实现小结:一个类可以实现多个接口,多个接口之间使用逗号分开;如果一个类实现了接口,就必须实现接口中的所有方法,否则这个类应该定义为抽象的;当使用其中一个接口来利用多态的形式使用实现类的对象时,只能访问属于这个接口的属性和方法;接口的多继承接口和类之间是实现的关系,接口和接口之间是继承的关系;而且接口支持多继承;3、接口的使用思想4.3.1