面向对象进阶
抽象类
引入:
学到继承的时候,重写的概念,子类对象调用方法,调用的是重写之后的方法,父类方法被隐藏,虽然用不到,但是是真实存在的,对于这样的方法能不能省略?
抽象类或者接口可以帮我们实现。
使用抽象方法
抽象类的概念
类的作用是用来创建对象的,但是并不是所有的类都是用来创建对象,像这样的类我们定义为或者称之为抽象类。像这样的类有哪些呢?(一般作为父类)
抽象类的定义方式
public abstract class 类名{
}
总结一下:class前面由abstract关键字修饰的类我们称之为抽象类
抽象类特点:
<1>.抽象类设计的目的是为了定义一些无需创建对象的类,所以抽象类本身无法实例化的(一般作为父类)
<2>.抽象类中可以拥有抽象方法。
<3>.抽象类还拥有普通类能够拥有的所有内容。
<4>.一般抽象类做为父类被子类继承之后产生作用。
抽象方法定义方式
抽象方法:由abstract关键字修饰的方法称之为抽象方法,抽象方法没有方法体。
public abstract 返回值 方法名(参数列表);
抽象方法的特点:
<1>.由abstract关键字修饰的方法
<2>.没有方法体;
<3>.abstract抽象方法不能使用final关键字修饰。(因为抽象方法必须被重写才能使用,而final关键字修饰的方法不能被重写)
<4>.抽象方法不能使用static关键字修饰(因为被static修饰的资源加载到静态区,而抽象方法没有方法体,不占用内存);
<5>.非抽象类继承一个抽象类那么必须强制重写这个抽象方法,否则编译不通过 。
<6>.因为只有抽象类中才可以拥有抽象方法。
抽象类中的常见问题
提问:
1.一个非抽象的子类继承一个抽象类,那么在非抽象子类中可以使用super关键字吗?为什么?
不可以,因为抽象类无法实例化,无法创建对象,而super是父类对象。
2.实例化的时候,系统会默认调用构造方法,抽象类不可以实例化,那么抽象类中存在构造方法吗?如果存在,那么构造方法有什么存在的意义?
有,在子类的构造方法的第一句调用。
3.一个非抽象子类继承一个抽象类,在子类的构造方法中可以调用父类构造方法吗?
可以
4.一个抽象类可以继承一个抽象类吗?如果可以那么继承过来的抽象方法该怎么处理?
可以,对于继承过来的抽象方法,我既可以重写,也可以不重写,因为抽象类中,可以存着抽象方法,也可以存着普通方法。
5.有抽象方法的类一定是抽象类吗?
是的。
6.抽象类一定有抽象方法吗?
不一定。可以没有方法。
抽象类的练习
<1>.设计一个Animal抽象父类 拥有run()方法其子类为 Pet类
设计一个抽象类Pet 宠物类,拥有抽象方法eat(),sound()方法
再设计2个子类,Dog,Cat,重写方法
<2>.测试静态方法,final关键字修饰的方法能不能定义为抽象方法...
<3>.抽象类的扩展应用(了解一下)
接口
引入
生活的接口:
USB接口:各个厂商在生产与USB接口相关产品的时候按照相同的规范生产产品,比如电脑,转接头等。
插座:各种电器厂商生产电器的时候,插口按照插座的规范去生产电器。
耳机,充电线等等...
总结:就一个统一规范,或者说是定义一个标准。
开发中的接口:定义开发的规则规范
比如我要做网站开发,我们遵循Servlet接口的规范。
如果没有接口,没有规范...
A公司 用自己的规范 AServlet aGet(),aPost()...
B公司 用自己的规范 BServlet bGet(), bPost()...
如果没有这些标准,那么换一家公司,这又得重新学习。
为了管住这些程序员,设置统一的规则规范,全世界的程序员按照统一规范。
Java类属于单继承
接口可以多继承
接口的概念
接口就是,抽象功能的集合,专门用于定义规范的。
接口的特点:
<1>.接口中一般只能定义抽象方法(jdk1.8之后还可以有默认方法,还能有静态方法)以及静态常量。
<2>.接口不能实例化,也没有构造方法。
<3>.接口与接口之间可以多继承
接口的定义方式:
public interface 接口名{
}
注意:
<1>.接口不是一个类,使用interface关键字修饰。
<2>.接口与接口之间可以互相继承,而且属于多继承。 extends
<3>.类不能继承接口,但是可以实现接口,而且是多实现接口。实现的关键字 implements
<4>. 接口中可以存着静态常量,里面的静态常量可以省略final static 。
比如 final static int num=100; 等价于 int num=100;
<5>.接口中可以存着抽象方法 ,一般abstract可以省略。
public abstract void method();
等价于
(public) void method();
---------------------------------------------------------------------------------------
提几个问题:
1.接口能不能继承抽象类?
答:不能继承抽象类
2.抽象类能不能继承接口?
答:不能继承但是可以实现,而且是多实现?
3.抽象类可以多实现接口,里面抽象方法一定要实现吗?
答:不需要的,因为抽象类中可以存着抽象方法
4.非抽象类可以多实现接口,里面的抽象方法必须要强制实现吗?jdk1.8之后默认方法呢?
答:必须要强制实现接口中的所有抽象方法,默认方法不一定要求强制实现。
练习一(类可以多实现接口)
代码实现方式:
MyCollection 接口定义了 定义相应功能(add(),remove(),size())
public interface MyCollection {
//1.静态常量
public int NUM_SIZE=0;
//2.抽象方法
public void add();
public void remove();
public void size();
//3.默认方法 default关键字修饰
public default void method1() {
}
//4.静态方法
public static void method2() {
}
}
还想拥有一些的新的方法
再定义一个新的接口 MyLinkedList
addFirst();
addLast();
其子类
MyLink 类实现了MyCollection 以及MyLinkedList (多实现....)
public class MyLink implements MyCollection,MyLinkedList{
@Override
public void add() {
System.out.println("添加....");
}
@Override
public void remove() {
System.out.println("删除...");
}
@Override
public void size() {
System.out.println("获得容器大小...");
}
@Override
public void method1() {
System.out.println("重写默认方法...");
}
@Override
public void addFirst() {
System.out.println("添加首元素...");
}
@Override
public void addLast() {
System.out.println("添加末尾元素...");
}
}
练习二(接口之间的多继承)
违反接口隔离原则
1.门Door 拥有开门和关门的方法 拥有独有的功能方法 防火防烟门 ,现要求设计一个多功能门规范,功能尽可能多。如果还有求设计其他的门呢?
public interface Door {
public void open();
public void close();
}
public interface FirePrevention {
public void preFire();
}
public interface SmokePrevention {
public void preSmoke();
}
多功能的规范为:
//1.定义了一个多功能门的规范...
public interface MultiFunctionDoor extends Door,FirePrevention,SmokePrevention{
}
接口与接口之间可以实现多继承...
分析使用默认方法的意义
jdk1.8之前不支持默认方法
Filter 接口
init();
doFilter();//真正做过滤的方法
destroy();
public interface Filter {
//jdk1.8之前只允许存在抽象方法
public void init();
public void doFilter();
public void destroy();
}
//实现接口需要强制实现所有的方法,哪怕很多方法我们并没有用到也得重写所有的。
public class LoginFilter implements Filter{
@Override
public void init() {
}
@Override
public void doFilter() {
System.out.println("关于登录的一个过滤器...");
}
@Override
public void destroy() {
}
}
jdk1.8之前如何解决此问题?
可以为Filter重新设计一个类FilterAdapter 一般会设计成抽象类
public abstract class FilterAdapter implements Filter{
@Override
public void init() {
}
@Override
public void doFilter() {
}
@Override
public void destroy() {
}
}
然后修改LoginFilter
public class LoginFilter extends FilterAdapter{
@Override
public void doFilter() {
System.out.println("关于登录的一个过滤器...");
}
}
jdk 1.8之后可以使用默认方法很好地解决上述问题
public interface Filter {
//1.jdk1.8或者以上允许存在默认方法
public default void init() {}
public default void doFilter() {}
public default void destroy() {}
}
实现类:
public class LoginFilter implements Filter{
@Override
public void doFilter() {
System.out.println("重写接口中的默认方法完成登录过滤...");
}
}
多态
多态的概述
多态:执行同一个操作,由于对象不同,最终返回结果不同。
引入:
H2o
在标准大气压下:
0摄氏度以下称之为冰
0-100摄氏度之间称之为水
100摄氏度以上称之为水蒸气
关于开发中多态的应用:
1.比如集合这一块,如下图所示:
实现多态的几个条件
Pet
Cat extends Pet
Dog extends Pet
1.必须存在继承关系
2.子类对象指向父类的引用(子类转父类默认进行的)
多态的2中形式:
<1>.public void startEat(Pet pet){};// startEat(new Dog()); start(new Cat());
<2>.public Pet getPet(){} return new Dog() 同时也可以返回return new Cat();// (了解)
多态的优势
1.有继承,但是没有多态的情况下。
设计喂养方法
public class Master {
public void feed(Cat cat) {
cat.eat();
System.out.println("吃完之后...");
cat.sound();
}
public void feed(Dog dog) {
dog.eat();
System.out.println("吃完之后...");
dog.sound();
}
public void feed(Penguin pg) {
pg.eat();
System.out.println("吃完之后...");
pg.sound();
}
}
没有多态我们需要重复设计多个方法完成同一个操作(都是喂养)
出现代码冗余,降低开发效率。
2.如果采用多态的思维方式解决此类问题
public void feed(Pet pet) {
pet.eat();
System.out.println("吃完之后...");
pet.sound();
}
因为子类转父类是默认进行的,也就是说调用feed方法传递的参数只要属于Pet类型即可(子类或者后代类都可以)
总结一下多态的优势:
减少代码冗余,提高程序的可扩展性,提高开发效率。。。
多态的综合练习:
使用打印机打印纸张
打印机(彩色打印机,黑白打印机)
纸张(A4,A5纸张)
Master
startPrint(){
}
由于条件不同最终返回的结果不同
<1>.选择彩色打印机,A4纸张 ==>结果彩色A4纸张
<2>.选择的是彩色打印机 A5纸张 ===> 结果彩色A5纸张
.....