java的多态:多态时面对对象的第三大特征;
- 方法的多态:方法的重载【本质:方法是由方法名 + 形参标识】和重写【本质是继承,实现】;
- 对象的多态:一个对象的声明类型【编译类型】和运行类型可以不一致,这个是多态的本质;
- 赋值符号左边是声明类型,右边是实际运行;
- 为什么有多态:
- 因为子类继承了父类的方法和属性,子类 new 空间内,存在一个独立的空间存放父类的属性,即除了private修饰的变量和方法【也有这些资源,只是不可访问】,子类访问可以其他任何资源;
- 因此,可以将子类看作特殊的父类,可以赋值给父类引用变量;
- 多态的向上转型
- 支持访问的成员【方法和属性,遵守访问权限】;
- 在编译阶段,由声明类型确定,不能调用子类的特有成员;
- 在运行阶段,与访问成员规则一致,查找的起点:
- 方法从动态对象开始查找;
- 属性从声明类型处开始查找;
- 有,就查看访问权限,可以访问,正常。不可访问,报错。如果没有。再递归到父类,接着判断;
- 多态的向下转型:【为了避开编译阶段的限制,能访问子类独有方法和属性】
- 为了避开编译阶段的限制,使用强制类型转换【转换的是父类的引用变量】,将声明的类型转化为子类,此时,编译类型和运行类型一致,在遵守访问权限的情况,能访问一切拥有的成员;
- 前提是必须存在继承或实现关系,否则报错;
- 对象的多态性:只适用于方法,但是属性没有多态性,
- 对象的属性是静态绑定:
- 属性的值在编译和运行都看左边【声明类型】
- 属性输出的值由声明类型确定,父类和子类的属性,同时存在当前对象中,并且都有构造器显式初始化,所以属性没有重写;
- 当声明类型没有,递归的到声明类型的父类【遵守相同的查找规律】;
- 当调用对象属性的时,哪里有声明,那里就使用,【类似于将整个类代码作为一个代码块{},属性就类似于代码块内的变量】
- 可以通过封装成方法进行动态访问,方法内的对象属性是运行的类型的属性【getter】;
- 对象的方法是动态绑定:
- 在运行阶段,当调用方法时,该方法都会和运行类型对象绑定;无论是调用父类方法中的方法的调用,第一反映是去运行类型中查找,然后再递归到父类查找;
- 对象的属性是静态绑定:
- 编译期间的绑定就是静态绑定,运行期间的绑定就是动态绑定,java为了实现多态的这个机制,选择让方法在运行期间绑定对应对象所对应实际类型,选择让属性在编译期间绑定其所对应实际类型。