day09.抽象 多态 接口
课前回顾:1.封装this:代表当前对象,哪个对象调用this所在的方法,this就代表哪个对象区分重名的成员变量和局部变量无参构造:new 对象不写jvm默认给一个有参构造:new 对象为属性赋值如果写了有参构造,无参构造就没了,所以我们都手写上标准的javabean:私有属性 无参构造 有参构造 get/set方法2.继承:关键字:extends成员访问特点:成员变量:看等号左边是谁先调用谁成员方法:看new的是谁先调用谁,子类没有找父类重写:前提:有子父类继承关系使用场景:功能的增强,更新特点:继承只支持单继承,不能多继承继承支持多层继承一个父类可以拥有多个子类3.super和thissuper:代表父类对象调用父类的构造:super()->super必须在构造第一行调用父类的成员变量:super.成员变量名调用父类的成员方法:super.成员方法名this:代表的当前对象调用当前类的构造:this()->this也要在构造第一行,所以,不能和super一起使用调用当前类的成员变量:this.成员变量调用当前类的成员方法:this.成员方法4.代码块:构造代码块{代码}优先于构造方法执行,且每new一次,构造代码块就执行一次静态代码块:static{}优先于构造方法和构造代码块执行的,只执行一次今日内容:1.会定义抽象类,以及会利用子类去实现抽象方法2.知道抽象类的特点3.会在多态的前提下访问成员4.知道多态的好处5.会定义接口,在接口中定义抽象方法,成员变量,默认方法,静态方法6.会定义实现类实现接口
第一章.抽象
![day09[抽象_多态_接口] - 图1](/uploads/projects/liuye-6lcqc@vk53cd/37c93298162bc62848442597ae2b786a.png)
1.抽象的介绍
1.抽象方法怎么形成:当将所有类的共性方法抽取到父类中,发现方法无法做具体实现(因为每个子类对这个方法的实现不一样),所以此方法抽取出来之后就可以定义为"抽象方法"2.抽象类怎么形成:抽象方法所在类一定是抽象类3.抽象类和抽象方法是一种代码设计理念因为抽象方法抽取出来之后,可以作为一个标准,规定,凡是我的子类都必须拥有这个方法,且必须要去做具体实现4.抽象类和抽象方法的特点a.抽象方法所在的类一定是抽象类b.抽象类中不一定非得有抽象方法(还可以包含:私有属性,构造,普通的成员方法)c.子类继承抽象父类,需要重写父类中的抽象方法d.抽象类不能直接new对象,需要通过子类做具体实现
1.关键字:abstract->抽象2.抽象类的定义:public abstract class 类名{}3.抽象方法:public abstract 返回值类型 方法名();4.注意:抽象方法必须要重写
public abstract class Animal {public abstract void eat();}
public class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗啃骨头");}}
public class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}}
public class Test {public static void main(String[] args) {//Animal animal = new Animal();抽象类不能直接new对象Dog dog = new Dog();dog.eat();System.out.println("================");Cat cat = new Cat();cat.eat();}}
2.抽象的注意事项
1.抽象类不能直接new对象的,只能创建其非抽象子类的对象。2.抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员(属性)使用的。3.抽象类中,可以有成员变量。4.抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。5.抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
public abstract class Animal {private String name;private String color;public Animal() {}public Animal(String name, String color) {this.name = name;this.color = color;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}//定义抽象方法public abstract void eat();public abstract void drink();}
public class Dog extends Animal{public Dog() {}public Dog(String name, String color) {super(name, color);}@Overridepublic void eat() {System.out.println("狗啃骨头");}@Overridepublic void drink() {System.out.println("狗喝水");}}
public abstract class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}}
public class Test {public static void main(String[] args) {Dog dog = new Dog("二哈", "黑白");}}
第二章.综合案例
某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部、维护部)。研发部(Developer)根据所需研发的内容不同,又分为 JavaEE工程师 、Android工程师 ;维护部(Maintainer)根据所需维护的内容不同,又分为 网络维护工程师 、硬件维护工程师 。公司的每名员工都有他们自己的员工编号、姓名,并要做它们所负责的工作。工作内容:- JavaEE工程师: 员工号为xxx的 xxx员工,正在研发淘宝网站- Android工程师:员工号为xxx的 xxx员工,正在研发淘宝手机客户端软件- 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通- 硬件维护工程师:员工号为xxx的 xxx员工,正在修复打印机请根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。
![day09[抽象_多态_接口] - 图2](/uploads/projects/liuye-6lcqc@vk53cd/32cbb4351e5cdecad8a3fa9368d1e616.png)
方式1:利用set赋值
//员工类public abstract class Employee {private int id;private String name;public Employee() {}public Employee(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}//抽象方法public abstract void work();}
//研发部public abstract class Developer extends Employee{}
public class JavaEE extends Developer{@Overridepublic void work() {System.out.println("编号为:"+this.getId()+"的"+this.getName()+"员工正在搞网站");}}
public class Android extends Developer{@Overridepublic void work() {System.out.println("编号为:"+getId()+"的"+getName()+"员工正在搞APP");}}
public class Test {public static void main(String[] args) {JavaEE javaEE = new JavaEE();//为属性赋值javaEE.setId(1);javaEE.setName("柳岩");javaEE.work();System.out.println("===========");Android android = new Android();android.setId(2);android.setName("杨幂");android.work();}}
方式2:利用构造赋值
//员工类public abstract class Employee {private int id;private String name;public Employee() {}public Employee(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}//抽象方法public abstract void work();}
public abstract class Developer extends Employee{public Developer() {}public Developer(int id, String name) {super(id, name);}}
public class JavaEE extends Developer{public JavaEE() {}public JavaEE(int id, String name) {super(id,name);}@Overridepublic void work() {System.out.println("编号为:"+this.getId()+"的"+this.getName()+"员工正在搞网站");}}
public class Android extends Developer{public Android() {}public Android(int id, String name) {super(id, name);}@Overridepublic void work() {System.out.println("编号为:"+getId()+"的"+getName()+"员工正在搞APP");}}
public class Test {public static void main(String[] args) {//使用构造方法为属性赋值JavaEE javaEE1 = new JavaEE(3, "金莲");javaEE1.work();}}
小结:
关键字:abstract
抽象方法: public abstract 返回值类型 方法名();
抽象类:public abstract class 类名{}
注意:
抽象方法所在的类一定是抽象类
抽象类不一定非得有抽象方法
抽象类中还可以有(私有属性,构造,普通的成员方法)
抽象类不能直接new对象
子类继承抽象父类之后,必须要重写抽象方法
第三章.多态
怎么学多态1.会使用多态的形式创建对象2.知道多态的好处
1.多态的介绍
1.面向对象三大特征:封装 继承 多态2.前提:a.必须有子父类继承关系或者接口实现关系b.必须有方法的重写->没有方法重写多态没有意义(利用多态访问成员变量,没任何意义)c.创建对象:父类引用指向子类对象父类 对象名 = new 子类()3.弊端利用多态的形式new对象,不能直接调用子类特有方法
2.多态的基本使用
1.创建父类2.创建子类继承父类3.在子类中重写方法4.利用多态形式创建对象:父类 对象名 = new 子类()5.调用子类重写的方法
public abstract class Animal {public abstract void eat();}
public class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗啃骨头");}//特有方法public void lookDoor(){System.out.println("狗会看门");}}
public class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}//特有方法public void catchMouse(){System.out.println("猫会抓老鼠");}}
public class Test {public static void main(String[] args) {Animal animal = new Dog();animal.eat();//animal.lookDoor();多态形式不能调用子类特有功能System.out.println("=============");Animal animal1 = new Cat();animal1.eat();}}
3.多态的条件下成员的访问特点
3.1成员变量
看等号左边是谁,先调用谁->成员变量没有多态性
public class Fu {int num = 100;}
public class Zi extends Fu{int num = 10;}
public class Test {public static void main(String[] args) {Zi zi = new Zi();System.out.println(zi.num);Fu fu = new Zi();System.out.println(fu.num);}}
3.2成员方法
看new的是谁先调用谁中的方法,子类没有,找父类->成员方法是有多态性的
public class Fu {int num = 100;public void method(){System.out.println("我是父类中的method方法");}}
public class Zi extends Fu{int num = 10;public void method(){System.out.println("我是子类中的method方法");}}
public class Test {public static void main(String[] args) {Zi zi = new Zi();System.out.println(zi.num);zi.method();//调用重写的Fu fu = new Zi();System.out.println(fu.num);fu.method();//调用重写的}}
4.多态的好处(为什么学多态)
1.多态的好处不体现在new对象上,体现在方法参数传递上2.不用多态和同多态有什么好处和弊端:不用多态:好处:既可以调用从父类继承过来的,还能调用重写的,还能调用自己特有的方法弊端:在传参数的过程中扩展性很差多态:弊端:不能直接调用子类特有方法好处:在传递参数的过程中扩展性强
public abstract class Animal {public abstract void eat();}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}//特有方法public void lookDoor(){System.out.println("狗会看门");}}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}//特有方法public void catchMouse(){System.out.println("猫会抓老鼠");}}
public class Test {public static void main(String[] args) {//原始方式new对象Dog dog = new Dog();method(dog);Cat cat = new Cat();method(cat);}public static void method(Animal animal){//Animal animal = dog; Animal animal = catanimal.eat();}}
5.多态中的转型
5.1向上转型
1.默认: 父类引用指向子类对象父类类型 对象名 = new 子类对象好比: doule b = 10;
5.2向下转型
1.如果想要调用子类特有方法,就需要向下转型2.怎能转:父类类型 对象名 = new 子类对象->向上转型子类类型 对象名1 = (子类类型)对象名->向下转型好比:double b = 10;->将int转成了doubleint i = (int)b;->将double强转成了intAnimal animal = new Dog();->向上转型Dog dog = (Dog)animal;-->向下转型
public abstract class Animal {public abstract void eat();}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}//特有方法public void catchMouse(){System.out.println("猫会抓老鼠");}}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}//特有方法public void lookDoor(){System.out.println("狗会看门");}}
public class Test {public static void main(String[] args) {Animal animal = new Dog();animal.eat();//向下转型Dog dog = (Dog)animal;dog.lookDoor();System.out.println("=================");Animal animal1 = new Cat();animal1.eat();//向下转型Cat cat = (Cat) animal1;cat.catchMouse();}}
6.转型可能会出现的问题
1.向下转型时注意的问题:如果等号左右两边类型不一致时:ClassCastException(类型转换异常)2.如何去判断类型:关键字:instanceof -> 结果是一个boolean型使用格式: 对象名 instanceof 具体类型关键字前面的对象是否属于关键字后面的类型
public abstract class Animal {public abstract void eat();}
public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}//特有方法public void lookDoor(){System.out.println("狗会看门");}}
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}//特有方法public void catchMouse(){System.out.println("猫会抓老鼠");}}
public class Test {public static void main(String[] args) {Dog dog = new Dog();method(dog);method(new Cat());}public static void method(Animal animal){if (animal instanceof Dog){animal.eat();Dog dog = (Dog) animal;dog.lookDoor();}if (animal instanceof Cat){animal.eat();//将代表dog的animal强转成CatCat cat = (Cat)animal;cat.catchMouse();}}}
小结:
1.前提:
a.必须有子父类继承关系或者接口实现关系b.必须有方法的重写(多态没有方法的重写,多态没有意义)c.父类引用指向子类对象2.成员访问特点:
成员变量:看等号左边是谁,先调用谁成员方法:看new的是谁,先调用谁,子类没有找父类3.多态的好处:
弊端:不能调用子类特有的方法好处:当作为方法参数传递的时候,扩展性强4.转型
向上转型:默认 父类引用指向子类对象向下转型:强转,将父类类型强转会子类类型
5.转型容易出现的问题:ClassCastException(类型转换异常)
原因:等号左右两边的类型不一致解决:做判断对象名 instanceof 类型->可以判断类型
第四章.接口
1.接口的介绍
1.概述:标准,规则,引用数据类型2.关键字:interface(接口) implements(实现)3.成员比较单一的jdk7:抽象方法:带abstract的方法 不写也有成员变量:带static final的,表示最终的变量,所以值不能改变 不写static final也有jdk8:默认方法:public default 返回值类型 方法名(参数){}静态方法:public static 返回值类型 方法名(参数){}jdk9:私有方法:private 返回值类型 方法名(参数){}
![day09[抽象_多态_接口] - 图3](/uploads/projects/liuye-6lcqc@vk53cd/21d1fa37f5d780ee9d891b52527f83f0.png)
2.接口的定义以及使用
1.定义:public interface 接口名{}2.定义实现类public class 类名 implements 接口名{重写接口中的抽象方法}3.注意:a.定义接口之后需要实现类去实现它b.实现类实现接口的时候,要重写接口中的抽象方法c.接口不能new对象,只能通过new实现类对象调用重写的方法
public interface USB {//定义抽象方法public abstract void open();void close();}
public class Mouse implements USB{@Overridepublic void open() {System.out.println("鼠标插进去打开了");}@Overridepublic void close() {System.out.println("鼠标拔出来就关闭了");}}
public class Test01 {public static void main(String[] args) {//USB usb = new USB();接口不能直接new对象Mouse mouse = new Mouse();mouse.open();mouse.close();System.out.println("=================");//利用多态的形式去newUSB usb = new Mouse();usb.open();usb.close();}}
3.接口中的成员
3.1抽象方法
1.定义:public abstract 返回值类型 方法名(参数);2.使用:a.定义实现类实现接口b.在实现类中重写抽象方法c.new实现类对象,调用重写方法3.注意:如果在接口中定义一个没有方法体的方法,就是抽象方法即使不写abstract,默认也有
public interface USB {//定义抽象方法public abstract void open();//没有写abstract,默认也有void close();}
public class KeyBoard implements USB{@Overridepublic void open() {System.out.println("键盘开启");}@Overridepublic void close() {System.out.println("键盘关闭");}}
public class Test {public static void main(String[] args) {KeyBoard keyBoard = new KeyBoard();keyBoard.open();keyBoard.close();System.out.println("=================");//多态形式USB usb = new KeyBoard();usb.open();usb.close();}}
3.2默认方法
1.定义:public default 返回值类型 方法名(参数){方法体return 结果}2.使用:a.定义实现类,实现接口b.如果不对接口中的默认方法进行功能修改,就不用重写了如果要对接口中的默认方法进行功能修改,就需要重写默认方法(不要带default)c.创建实现类对象,调用默认方法或者重写的方法
public interface USB {//默认方法public default void start(){System.out.println("USB打开了");}}
public class Mouse implements USB{@Overridepublic void start(){System.out.println("鼠标打开了");}}
public class Test {public static void main(String[] args) {Mouse mouse = new Mouse();mouse.start();}}
3.3静态方法
1.定义格式:public static 返回值类型 方法名(参数){方法体return 结果}2.使用:接口名直接调用
public interface USB {//静态方法public static void start(){System.out.println("usb开启了");}}
public class Test {public static void main(String[] args) {USB.start();}}
在类中定义的静态方法,也不能被重写
3.4成员变量
1.定义格式:public static final 数据类型 变量名 = 值即使不写public static final默认也有2.使用:接口名直接调用3.注意:a.接口中的成员变量即使不写public static final默认也有b.接口中的成员变量需要手动赋值c.接口中的成员变量不能被二次赋值d.被static final修饰的变量名字一般都要大写(习惯上的写法)
public interface Interface {public static final int NUM = 100;//num = 200;被final修饰的成员变量不能被二次赋值int I = 10;}
public class Test {public static void main(String[] args) {System.out.println(Interface.NUM);}}
4.接口的特点
1.接口可以多继承public interface InterfaceC extends InterfaceA,InterfaceB{}2.一个实现类可以同时实现一个或者多个接口->需要重写接口中所有的抽象方法public class InterfaceImpl implements InterfaceA,InterfaceB{}3.一个实现类可以继承一个父类的同时实现一个或者多个接口->需要重写父类中和接口中所有的抽象方法public class Zi extends Fu implements InterfaceA,InterfaceB{}
如果抽象方法有重名的,只需要重写一次
如果默认方法有重名的,必须重写一次
5.接口和抽象类的区别
相同点:都位于继承的顶端,用于被其他类实现或继承;都不能直接实例化对象;都包含抽象方法,其子类都必须重写这些抽象方法;不同点:抽象类:一般作为父类使用,可以有成员变量 构造方法 成员方法等接口:成员单一,一般抽取接口,抽取的都是方法,是功能的大集合类不能多继承,但是接口可以
6.综合练习
定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用;进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘- USB接口,包含开启功能、关闭功能- 笔记本类,包含运行功能、关机功能、使用USB设备功能- 鼠标类,要符合USB- 键盘类,要符合USB接口
![day09[抽象_多态_接口] - 图4](/uploads/projects/liuye-6lcqc@vk53cd/0330dbc08d68b240a7ddecad44117237.png)
public interface USB {//开启void open();//关闭void close();}
public class Mouse implements USB{@Overridepublic void open() {System.out.println("鼠标开启");}@Overridepublic void close() {System.out.println("鼠标关闭");}}
public class KeyBoard implements USB{@Overridepublic void open() {System.out.println("键盘开启");}@Overridepublic void close() {System.out.println("键盘关闭");}}
public class NoteBook {//开机public void start(){System.out.println("开机了,来啊,使用我呀");}//使用USB方法public void useUsb(USB usb){usb.open();usb.close();}//关机public void stop(){System.out.println("关机了,你不要来了");}}
public class Test {public static void main(String[] args) {//创建鼠标和键盘对象Mouse mouse = new Mouse();KeyBoard keyBoard = new KeyBoard();//创建笔记本类对象NoteBook noteBook = new NoteBook();noteBook.start();noteBook.useUsb(mouse);noteBook.useUsb(keyBoard);noteBook.stop();}}
![day09[抽象_多态_接口] - 图5](/uploads/projects/liuye-6lcqc@vk53cd/6a4a08ca63a3048d4371ad7752967081.png)
7.综合练习升级版
public interface USB {//开启void open();//关闭void close();}
public class Mouse implements USB{@Overridepublic void open() {System.out.println("鼠标开启");}@Overridepublic void close() {System.out.println("鼠标关闭");}//特有方法public void click(){System.out.println("我可以单击");}}
public class KeyBoard implements USB{@Overridepublic void open() {System.out.println("键盘开启");}@Overridepublic void close() {System.out.println("键盘关闭");}//特有方法public void input(){System.out.println("键盘输入");}}
public class NoteBook {//开机public void start(){System.out.println("开机了,来啊,使用我呀");}//使用USB方法public void useUsb(USB usb){if (usb instanceof Mouse){usb.open();usb.close();//向下转型Mouse mouse = (Mouse)usb;mouse.click();}if (usb instanceof KeyBoard){usb.open();usb.close();//向下转型KeyBoard keyBoard = (KeyBoard)usb;keyBoard.input();}}//关机public void stop(){System.out.println("关机了,你不要来了");}}
public class Test {public static void main(String[] args) {//创建鼠标和键盘对象Mouse mouse = new Mouse();KeyBoard keyBoard = new KeyBoard();//创建笔记本类对象NoteBook noteBook = new NoteBook();noteBook.start();noteBook.useUsb(mouse);noteBook.useUsb(keyBoard);noteBook.stop();}}
第五章.权限修饰符
5.1 概述
在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,
- public:公共的。
- protected:受保护的
- default:默认的,不写任何权限修饰符,那么整个权限就是默认权限
- private:私有的
5.2 不同权限的访问能力
| public | protected | default(空的) | private | |
|---|---|---|---|---|
| 同一类中 | √ | √ | √ | √ |
| 同一包中不同类(子类与无关类) | √ | √ | √ | x |
| 不同包的子类 | √ | √ | ||
| 不同包中的无关类 | √ |
可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:
- 成员变量使用
private,隐藏细节。 - 构造方法使用
public,方便创建对象。 - 成员方法使用
public,方便调用方法。
第六章.final关键字
1.概述:最终的2.用法:修饰类修饰方法修饰成员变量修饰局部变量修饰对象
1.final修饰类
1.格式:public final class 类名{}2.特点:被final修饰的类不能被继承
public final class Animal {public void eat(){System.out.println("动物要吃饭");}}public class Dog /*extends Animal*/{//被final修饰的类不能被继承}
2.final修饰方法
1.格式:public final 返回值类型 方法名(参数){方法体return 结果}2.特点:被final修饰的方法不能被重写
public abstract class Animal {public final void eat(){System.out.println("动物要吃饭");}//public abstract final void drink(); abstract和final冲突}public class Dog extends Animal{//被final修饰的方法不能被重写/* public void eat(){System.out.println("动物要吃饭");}*/}
