Java-面向对象特征-多态

多态polymorphic

【基本介绍】

方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

具体体现:

  1. 方法的多态:重写和重载就体现多态

  2. 对象的多态(核心,困难,重点)
    重要的几句话:
    (1)一个对象的编译类型和运行类型可以不一致
    (2) 编译类型在定义对象时,就确定了,不能改变
    (3) 运行类型是可以变化的
    (4) 编译类型看定义时 =号的左边,运行类型看 =号的右边

案例:Animal animal = new Dog();
(Dog类继承于Animal类)
(animal编译类型是Animal,运行类型Dog)

【初识例子】

Java-面向对象特征-多态
说明:Dog和Cat是Animal的子类,Bone和Fish是Food的子类

【多态的细节】

细节一:

多态的前提是:两个对象(类)存在继承关系。

多态的向上转型

(1)本质:父类的引用指向了子类的对象
(2)语法:父类类型 引用名 = new 子类类型();
(3)特点:编译类型看左边,运行类型看右边。

可以调用父类中的所有成员(需遵守访问权限);

不能调用子类中特有成员;【在编译阶段,能调用哪些成员,由编译类型来决定的】【向下转型后可以】

最终运行效果看子类的具体实现。

Java-面向对象特征-多态

若有对象:Aniaml animal = new Cat();

animal.catchMouse(); //编译报错

【编译类型】则该对象的编译类型是Animal,可以调用父类的sleep等方法,但是不能调用Cat类的catchMouse方法。不能调用的原因是编译器不通过,因为其编译类型是Animal,Animal类没有该方法

animal.eat();

animal.run();

animal.show();

animal.sleep(); //都可以运行

【运行类型】该对象的运行类型是Cat,所以当运行时,它还是先从Cat类中寻找这四个方法,找不到再往上级父类找,然后调用


细节二:

多态的向下转型

(1)语法:子类类型 引用名 = (子类类型)父类引用

Cat cat = (Cat)animal;

cat.catchMouse(); //可以运行

(2)只能强转父类的引用,不能强转父类的对象

(3)要求父类的引用必须指向的是当前目标类型的对象

Dog dog = (Dog)animal; //出现异常,如下图,它本该是只猫

(4)当向下转型后,可以调用子类类型中所有的成员

Java-面向对象特征-多态

相当于说,现在有两个引用指向这个cat对象,一个是父类的引用,一个是子类的引用


细节三:

属性没有重写之说,属性的值看编译类型

Java-面向对象特征-多态

instanceof 比较修饰符,用于判断对象的运行类型是否为XX类型或XX类型的子类型,运算的结果是true或false


【练习】

Java-面向对象特征-多态

Java-面向对象特征-多态

Java-面向对象特征-多态


【Java的动态绑定机制(非常非常重要)Dynamic binding】

  1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

Java-面向对象特征-多态

由代码可得,对象a的编译类型是 A ,运行类型是 B
所以a.sum()和a.sum1()都从运行类型 B 开始找。

若仅仅把子类的sum()方法注释掉,则此时的输出为 30 ,30
(运行时找到父类的sum方法,但是里面又包含一个getI方法,这个方法父类和子类都设置有;
根据动态绑定机制,这个getI方法会调用运行类型的该方法。)

若仅仅把子类的sum1()方法注释掉,则此时的输出为 40 ,20
(运行时找到父类的sum1方法,但是里面有一个属性i,这个属性父类的子类都设置有
根据动态绑定机制,这个i属性会调用此方法所在的类的属性。)


【多态数组】

数组的定义类型为父类类型,里面保存的实际元素类型为子类类型

Java-面向对象特征-多态

【多态参数】

方法定义的形参类型为父类类型,实参类型允许为子类类型

Java-面向对象特征-多态

public void showEmpAnnual(Employee e) {
	System.out.println("该员工"+e.getName()+"的年工资为:"+e.getAnnual());
}

public void testWork(Employee e) {
	if(e instanceof Worker) {
		Worker worker = (Worker)e; //向下转型,调用子类的方法
		worker.work();
	}else if(e instanceof Manager) {
		((Manager)e).manage(); //向下转型,调用子类的方法
	}
	
}

Java-面向对象特征-多态

上一篇:Android 自定义Dialog


下一篇:spring5 入门(八)声明事务