面向对象之多态 (简单地说:使用目的就是为了方法拓展)
1.多态的概念:一种事物的多种形态(状态)
举例: 人的多态
婴儿--->儿童--->少年--->青年--->中年--->老年
2.多态的规则
1️⃣必须类与类之间有关联(继承关系)
2️⃣必须有方法的重写(否则多态没有意义)
3️⃣(核心)父类的引用 指向 子类的空间(对象)
// 举例
// 动物类(共有的方法:吃)
// 猫类(吃鱼) 狗类(吃骨头)
class Animal{
public void eat(){
System.out.println("吃");
}
}
// 猫类
class Cat extends Animal{
public void eat() {
System.out.println("猫吃鱼");
}
}
// 狗类
class Dog extends Animal{
public void eat() {
System.out.println("狗吃骨头");
}
}
// 创建对象
public class Demo {
public static void main(String[] args) {
// 父类的引用 指向 父类对象空间
Animal a = new Animal();
a.eat();
// 使用多态的形式 创建对象
// 父类的引用 指向 子类对象空间
// 调用方法 最后执行的是子类重写的方法
Animal aCat = new Cat();
aCat.eat();
Animal aDog = new Dog();
aDog.eat();
}
}
多态在内存中的表现
当使用多态形式 创建对象时
(因为多态只在继承中体现,所以我们只说继承的两个方面:成员变量和成员方法)
访问成员变量(编译和运行都看父类的)
编译时: 需要看父类当中 有没有该变量(没有就报错)
运行时: 最终访问到的成员变量 是父类中的成员变量
访问成员方法(编译看父类,运行看子类)
编译时: 需要看父类当中 有没有该方法(没有就报错)
运行时: 最终运行时入栈执行的是 子类中重写的方法
// 多态在内存中表现举例
// 父类
class Father{
int num = 10;
public void print() {
System.out.println("我是Father类的打印方法");
}
}
// 子类
class Son extends Father{
int num = 20;
@Override // 方法重写的标识(加上是为了让计算机更好的识别)
public void print() {
System.out.println("我是Son类的打印方法");
}
}
// 创建对象
public class Demo {
public static void main(String[] args) {
// 创建Father 调用方法 打印num
Father a = new Father();
a.print();
System.out.println(a.num);
// 使用多态 创建对象 调用方法 打印num
Father b = new Son();
b.print();
System.out.println(b.num);// 10
}
}
// 结果
我是Father类的打印方法
num = 10
我是Son类的打印方法
num = 10
3.多态的好处
1️⃣减少代码量,提高工作效率,增加代码的复用性
2️⃣(核心) 增强方法的拓展性(前提: 使用父类当做方法参数时)
例如: 玩游戏时,武器是一个父类,各种武器如 刀枪棍棒都是子类.
比如每种武器都有自己的 特有的拾取,修炼等玩法
例如拾取这个方法,我们就可以利用武器类的所有子类对象
public static void pickup(WuQi wq){}
4.多态的弊端
1️⃣使用多态形式创建对象 无法直接调用子类的特有方法(要转型)
// 多态的弊端
// 父类: 人
class Person{
public void talk() {
System.out.println("聊天");
}
}
// 子类: 骗子
class Pz extends Person{
@Override
public void talk() {
System.out.println("洗脑");
}
public void hit() {
System.out.println("打人");
}
}
// 创建对象
// 使用多态 创建对象
// 向上转型 和 向下转型
// 将子类的对象做了一个向上的类型提升
Person a = new Pz();
// 调用共有方法
a.talk();
// 如何调用特有方法??
// 1.首先
/* 做一个类型判断
* instanceof
* 判断前面对象 属不属于 后面这个类的对象
* (参考string.equals(Object) Object instanceof string)
* 类型一致 返回true,反之 false
* 类型一致 才能向下转型
*/
// 2.转型
// 需要将类型向上转回来 类型的向下转型
// 将转上去的类型 转回来 才能调用子类的特有方法
**注意:必须是先有向上转型,才能向下转型**
// 强制转换
Pz pz = (Pz)a;// 向下转型
pz.hit();