多态、抽象、接口

多态

知识回顾:jvm特性:跨平台,多线程,面向对象,自动垃圾回收机制
面向对象特性:封装性,继承性,动态性(多态),抽象
变量的声明: 数据类型 变量名 = 值;
变量的分类:局部变量;方法内部声明的变量、也可以是参数列表声明的对象;
静态变量;使用static修饰的变量;
成员变量;没有使用static修饰的变量;

多态相关的知识点:
软件设计六大原则;
①里氏替换原则:能够使用父类的地方就一定可以使用子类;
②单一职责原则:功能单一,只拥抱一种变化;
③依赖倒置原则:高层通过抽象依赖底层;
④接口隔离原则:不依赖它不需要的接口;
⑤迪米特原则:最少知识原则,一个类对其他的类知道的越少越好,就像一个人之和亲属,朋友直接通信,不和陌生人说话;
⑥开闭原则:对扩展开放,对修改关闭;

什么是多态?
多态就是里氏替换原则的一种表现;
父类引用 指向 子类对象;
父类引用:父类型声明的引用类型变量;
引用:通过整个引用类型的变量可以找到谁;
子类对象:实例化的对象,用new声明的子类对象;
多态即为:通过父类创建的一个引用类型的变量,去找到用new声明的子类的对象;
用法: 父类对象 变量名 = new 子类(); 例如:Animal a = new Cat ();

声明情况可以发生多态?
有变量的地方就可以发生多态,并且多态是发生在赋值的时候;
Animal a = new Cat();
多态发生的几种形式:
①直接多态;不管是成员变量还是局部变量,直接声明发生多态; 父类 变量名 = new 子类();
②形参和实参;方法参数定义时,使用父类定义,调用方法时,传递子类对象;
③返回值;返回值类型定义为父类,返回数据的时候返回子类对象;

多态的缺点:丢失子类特有属性;即子类有的父类没有的属性;

多态调用属性:①如果是父类没有的,直接报错,访问不了;
②如果调用的是子类没有的,都访问父类的;
③如果调用的是父类和子类都有的,除成员方法调用子类的,其他都调用父类的;因为成员方法可以覆写;

发生多态的前提条件:
①必须在有继承关系的体系中;
②多态有叫向上转型;即父类可以访问子类继承父类的方法以及对父类方法的扩展(对父类方法的覆写);
多态又称向上转型,类似于变量的自动类型转换,从子类到父类的转换;
向上转型:可以看作是强制类型转换,从父类到子类;发生前提是,存在向上类型转换;

intanceof用来判断该对象是否由某个类的实例化而来;
多态的缺点:丢失子类特性,需要向下转型再访问;
属于编译时异常;

程序的生命周期:
编译阶段:在编译阶段时,父类文件子类文件都有,但是子类对象不存在,子类对象是在运行时才生成的;
我们在代码中定义了多态,编译器会直接按照父类类型来划分空间,说明空间中有什么,检查语法结构;
这时只能找到父类里面的属性说明,因为空间是父类声明的;
运行阶段:程序开始运行,各个类载入方法区,开始运行,执行new创建对象。对象用子类创建的,所以对象中是包含子类的特有属性的;
但是引用变量的类型是父类类型,并且在编译时就以已经进行了静态绑定,所以使用这个父类声明的空间的时候就只能找到父类中有的属性;
所以子类对象中的特有属性是没有办法通过父类的变量找到的;

编译时:
在编译的时候,父类的属性会生成一个属性列表,此时父类的属性就已经有了,这叫编译时绑定,绑定完了之后程序就有了;
属性值没有固定,因为程序都没有运行,这些操作都是在静态区/方法区完成的,栈内存与堆内存没有任何数据传入;
这种编译时的绑定,又称作静态绑定/前绑定;
运行时:
运行的时候,把类生成对应的对象,属性列表也随之生成;此时子类生成了实例化对象,有了空间进行初始化操作,子类的属性值也就有了;
这种在运行阶段进行的数据绑定叫做运行时绑定/动态绑定/后绑定;
调用时:
使用父类的引用调用子类的对象的属性时(子类特有的访问不到);
可以理解为使用父类的属性列表去调用子类的属性值列表(一一对应的关系,但是可能是一对多,多出来的即为子类特有属性);

super:官方说法,代表父类类型特征,可以理解为父类的属性列表;

使用多态调用结果:
①父类没有的,无论子类有无,都调用不了,直接编译时报错;
②父类有的,子类没有的,都执行父类的;
③父类与子类都有,除成员方法调用子类,其他都执行父类;
隐式多态
1.直接赋值
2.实参形参
3.返回值
4.隐式:类似于自动类型转换

抽象

abstract 是一个修饰符
使用abstract修饰的类是抽象类;
使用abstract修饰的方法是抽象方法,抽象方法没有方法体;只有功能定义,没有功能实现,功能实现由子类完成;
实现抽象方法,就是给抽象方法加上方法体,去掉abstract修饰
抽象类的目的:该类不能被实例化对象,只能被继承;
抽象方法一定在抽象类中成立;
抽象类中不一定有抽象方法,比如不想让某个类有对象,可以创建为抽象方法;
final 修饰的类不能被继承;
final 修饰的成员方法不能被覆写;
抽象类就是用于被继承的;
抽象方法就是用于被实现覆写的
因而fianl和abstract不能同时出现

一个类若想继承一个抽象类,必须要实现该抽象类的所有抽象方法;
一个抽象类如果想要继承一个抽象类,可以实现0~N个抽象方法;
虽然抽象类不能被创建对象,但是抽象类有构造方法,因为子类创建对象需要调用父类然后调用Object实现;
abstract 是不能修饰静态方法的,因为静态方法不能被覆写;

抽象类的应用场景:
例如在我们在定义父类的时候,只知道父类的功能,不知道如何实现;
例如动物都是会运动的;但是运动的方式不一样,有飞的、跑的、游的;
这时,我们就定义为抽象类说明功能,具体的实现由实现类去完成;

抽象方法与成员方法一样,仅仅是没有方法体而已;
抽象方法必须被覆写,成员方法根据需求覆写;

接口

引用数据类型: 类、数组、接口

接口是一种引用数据类型,可以看作是一种特殊的类,是java为了解决类之间不能多继承引起的功能变弱的问题;
一个类只能有一个父类,但是却能有N个接口;

创建接口的方式,class变interface;继承关系,extends变implements

类和类使用extends继承,属于单继承;
类和接口使用implements多实现,多个以逗号隔开;例如 class A implements B,C,D
同样的,非抽象类实现接口,必须实现所有的抽象方法;
抽象类实现接口,可以实现0~N个抽象方法

接口和接口使用extends,并且是多继承;例如 interface A extends B,C,D

语法:public interface 接口名 {

		}

1.接口中所有变量都是public static final 修饰的,也就是常量,通常将其省略;
2.接口中的方法,默认都是public abstract的,也就是抽象方法,同意将其省略;
3.接口中是没有构造方法的,不能被实例化对象,因为无法与Object建立连接;

从java 1.8开始 接口中可以有默认方法和静态方法;
接口可以看作是一个特殊的抽象类,所以很多时候,接口和抽象类都能做到某一个事情,优先使用接口;
因为类与接口之间是多实现的,当使用接口后,还可以保留类的继承;

猜你喜欢

转载自blog.csdn.net/MIRACLE_Ying/article/details/112753102