多态
指的是一种事物的多种形态(状态)
例子:卵-->蝌蚪-->青蛙-->青蛙妈妈
实现多态的前提
1.类与类必须有继承关系
2.必须有方法的重写
核心:父类的指针(引用) 指向 子类的 对象(子类的空间)
public class Demo01 { public static void main(String[] args) { //本类的引用(指针)指向本类的对象(空间) Man man = new Man(); man.eat(); //多态的对象创建方法 //父类指针指向子类的空间 Person1 aman = new Man();//父类的 引用(指针) 指向 子类对象(子类的空间) aman.eat(); Person1 awoman= new Woman(); awoman.eat(); } } /* * 需求: 创建 人类 男人类 女人类 都有一个吃的方法 人类 动物吃饭 男人 男人喝酒 女 女人化妆 */ class Person1 { public void eat() { System.out.println("人吃饭"); } } class Man extends Person1 { public void eat() { System.out.println("男人喝酒"); } } class Woman extends Person1 { public void eat() { System.out.println("女人化妆"); } }
多态如何使用成员变量
父类的引用指向子类的空间中 父类的那部分
编译:在子类中寻找父类的属性 如果找不到 就报错
运行:访问的是父类的成员变量
结论:当使用多态创建对象时 访问的成员变量 编译和运行都看父类
多态调用成员方法
编译:在子类中寻找父类的 成员方法 如果找不到就报错
运行:看子类的重写父类的方法
结论:重写方法时 编译看父类 运行看子类
public class Demo02 { public static void main(String[] args) { //多态的创建形式(画内存图) Father fSon = new Son(); fSon.print(); System.out.println(fSon.num); Son son = new Son(); son.print(); System.out.println(son.num); } } class Father { int num = 10; public void print() { System.out.println("我是父类的打印方法"); } } class Son extends Father { int num = 20; @Override public void print() { System.out.println("我是子类的打印方法"); } }
多态的好处:
1.提高代码的复用性 提高效率 代码的维护性加强(继承)
2.代码的扩展性增强
坏处:使用多态方法创建对象时不能直接调用子类的特有方法
注意:使用多态调用方法时必须先向上转型 在向下转
public class Demo03 {
public static void main(String[] args) { //多态对象创建 //提升骗子逼格 //提升子类对象的类型 --向上转型 Person p = new PianZi(); p.speak(); //如何调用子类特有方法 //把骗子打回原形 //向下转型---强制类型转换 PianZi pianZi=(PianZi)p; //调用子类的特有方法 pianZi.hit(); } } class Person{ public void speak() { System.out.println("聊天"); } } class PianZi extends Person{ public void speak() { System.out.println("洗脑"); } //特有方法 public void hit() { System.out.println("打人 威胁人"); } }多态的核心特点:提高方法扩展性;
举个例子
public class Demo04 { public static void main(String[] args) { Jian jian = new Jian(); fun(jian); Dao dao = new Dao(); fun(dao); } // 使用多态的方法 public static void fun(WuQi wuQi) { //调用子类中重写的方法 wuQi.hit(); //判断一下类型 //根据具体的类型进行向下转型 //判断 wuQi 是否属于 剑(类名)这个类的对象 if (wuQi instanceof Jian) { //改武器就是一把剑 //向下转型 Jian j=(Jian)wuQi; //调用特有的方法 j.LianJian(); }else if (wuQi instanceof Dao) { Dao d= (Dao)wuQi; d.LianDao(); } } } class WuQi { public void hit() { System.out.println("武器打"); } } class Jian extends WuQi { @Override public void hit() { System.out.println("剑-- 舞衣下"); } public void LianJian() { System.out.println("练习剑法"); } } class Dao extends WuQi { @Override public void hit() { System.out.println("砍人"); } public void LianDao() { System.out.println("练习刀法"); } }
上面个例子 扩展性体现在:如果我们要修改调用剑或者刀特有方法 只要从武器这个类入手就行
不需要 单独堆剑 或者 刀 进行分别调用;
下面有个练习 有时间看看
package com.lanou3g; /* * 铁桶僵尸 血量 * 方法:每次被打减少2滴血 直到被打死 打印铁桶死了 * * 门框僵尸 * 血量 * 方法:每次被打减少5滴血 直到被打死 打印 门框死了 * * main函数中 封装一个 打僵尸的方法 * 无参 有参 set get */ public class Demo07 { public static void main(String[] args) { TieTong tieTong = new TieTong(); tieTong.setBlood(200); hiJiang(tieTong); } public static void hiJiang(JiangShi jiangShi) { jiangShi.hit(); } } class JiangShi { // 成员变量私有化 private int blood; // 无参 有参 public JiangShi(int blood) { super(); this.blood = blood; } public JiangShi() { super(); // TODO Auto-generated constructor stub } public void hit() { System.out.println("僵尸被人殴打"); } // set get 方法 public int getBlood() { return blood; } public void setBlood(int blood) { this.blood = blood; } @Override public String toString() { return "Jiang [blood=" + blood + "]"; } } class TieTong extends JiangShi { // 被打方法重写 @Override public void hit() { while (true) { //判断血量 if (this.getBlood() <= 0) { System.out.println("铁桶僵尸死了"); break;//结束 } //一次2滴血 this.setBlood(this.getBlood() - 2); System.out.println("僵尸剩余血量" + this.getBlood()); } } } class MengKuang extends JiangShi { //别打方法重写 @Override public void hit() { //判断血量 if (this.getBlood() <= 0) { System.out.println("僵尸死了"); return;//结束 } //打一次减少5滴血 this.setBlood(this.getBlood() - 5); System.out.println("僵尸剩余血量" + this.getBlood()); this.hit();//调自己 } }