问题引导
- 使用传统的方法来解决(private 属性)
- 传统的方法带来的问题是什么? 如何解决?
问题是: 代码的复用性不高,而且不利于代码维护
解决方案: 引出我们要讲解的多态
多态的基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
多态的具体体现
方法的多态
重写和重载就体现多态
package com.hspedu.poly_;/*** @author:寰愬悏瓒�* @date:2024/12/4 version:1.0*/
public class PloyMethod {public static void main(String[] args) {
// 方法重载体现多态A a = new A();
// 传入不同的参数,就会调用不同的sum方法,就体现多态System.out.println(a.sum(10,20));System.out.println(a.sum(10,20,30));// 方法重写体现多态B b = new B();a.say();b.say();}
}class B {public void say() {System.out.println("B say()被调用....");}}class A extends B {public int sum(int n1,int n2) {return n1 + n2;}public int sum(int n1,int n2,int n3) {return n1 + n2 + n3;}public void say() {System.out.println("A say()被调用....");}
}
对象的多态
记住:
父类的引用 可以指向它子类的对象;
例子代码
Animal:
package com.hspedu.poly_.objectpoly_;public class Animal {public void cry() {System.out.println("Animal cry() 动物在叫。。。");}
}
Cat:
package com.hspedu.poly_.objectpoly_;public class Cat extends Animal {public void cry() {System.out.println("Cat cry()小猫喵喵叫...");}
}
Dog:
package com.hspedu.poly_.objectpoly_;public class Dog extends Animal {public void cry() {System.out.println("Dog cry()小狗旺旺叫...");}
}
PolyObject:
package com.hspedu.poly_.objectpoly_;public class PolyObject {public static void main(String[] args) {
// 体验对象多态特点
// animal 编译类型就是 Animal , 运行类型是 DogAnimal animal = new Dog();//因为运行时,这时候执行到改行时,animal运行类型是Dog,所以cry就是Dog的cryanimal.cry(); // 小狗旺旺叫animal = new Cat();animal.cry();// 小猫喵喵叫}
}
使用多态的机制来解决主人喂食物的问题,走代码
多态注意事项和细节讨论
多态的向上转型
1.先编译后运行,在编译的时候看父类有没有这个方法有的 话,编译才能通过,但是后面 运行的时候还是就近原则,先看子类有没有,有的话就调用子类的
2.特有成员(是指父类没有,子类有的成员)
3.成员是指属性和方法
代码:
Animal类
package com.hspedu.poly_.detail_;public class Animal {String name = "动物";int age = 10;public void sleep() {System.out.println("睡");}public void run() {System.out.println("跑");}public void eat() {System.out.println("吃");}public void show() {System.out.println("Hello,你好");}
}
Cat类
package com.hspedu.poly_.detail_;public class Cat extends Animal {public void eat() {System.out.println("猫吃鱼");}public void catchMouse() { // Cat特有方法System.out.println("猫抓老鼠");}
}
PolyDatail类
package com.hspedu.poly_.detail_;public class PolyDatail {public static void main(String[] args) {// 向上转型: 父类的引用指向了子类的对象
// 语法: 父类的类型引用名 = new 子类类型();Animal animal = new Cat();Object obj = new Cat(); //Object 也是 Cat的父类;// 向上转型调用方法的规则如下:
// (1)可以调用父类中的所有成员(需遵守访问权限)
// (2)但是不能调用子类的特有成员(是指父类没有,子类有的方法)
// (3)因为在编译阶段,能调用哪些成员,是由编译类型来决定的
// animal.catchMouse(); 错误// (4)最终运行效果 看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法,
// 然后调用,规则同前面讲的方法调用规则 一致。
animal.eat(); // 猫吃鱼
animal.show(); // Hello,您好
animal.sleep(); // 睡
animal.run(); // 跑}
}
多态的向下转型
在
1.animal 现在的编译类型还是 Animal
2.强制类型转换只是将animal引用的对象视为Cat类,而不是真的将其转换为Cat类;
3.现在的 animal编译类型是:Animal,运行类型是:Cat
4.现在的 Cat编译类型是:Cat,运行类型是:Cat
修改 上述 PolyDatail类
// (4)最终运行效果 看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法,
// 然后调用,规则同前面讲的方法调用规则 一致。
animal.eat(); // 猫吃鱼
animal.show(); // Hello,您好
animal.sleep(); // 睡
animal.run(); // 跑// 目的: 希望,可以调用Cat的 catchMouse();
// 多态的向下转型;
// (1)语法:子类类型 引用名 = (子类类型)父类引用;
// 问一个问题? cat 的编译类型是 Cat, 运行类型是 CatCat cat = (Cat) animal;cat.catchMouse(); //猫抓老鼠
// (2)要求父类的引用必须指向的是当前目标类型的对象;}
}
属性没有重写之说!属性的值看编译类型
属性没有重写之说!属性的值看编译类型,方法看运行类型
package com.hspedu.poly_.detail_;public class PolyDetail03 {public static void main(String[] args) {BB bb = new BB();System.out.println(bb instanceof BB);// trueSystem.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
//BB 是 AA 子类AA aa = new BB();System.out.println(aa instanceof AA);// trueSystem.out.println(aa instanceof BB);// trueObject obj = new Object();System.out.println(obj instanceof AA);//falseString str = "hello";
//System.out.println(str instanceof AA);System.out.println(str instanceof Object);//true}
}class AA {} //父类class BB extends AA {} // 子类
练习1
解析:
1.double不多介绍 了
2.double -> long 自动类型转换
3.int -> boolean 错误
4.String类是 Object的子类,当然 可以 向上/向下转型了
5.Integer就是int ,也是 Object的子类