Java中的多态
1.JAVA的多态用一句话能直观的解释一下:
事物在运行过程中存在不同的状态。
2.多态存在的三个前提
1.类与类之间要有继承关系
2.子类要重写父类的方法
3.(核心)父类引用(指针)指向子类对象(子类的空间)
2.多态的优点
1. 消除类型之间的耦合关系
2. 可替换性
3. 可扩充性
4. 接口性
5. 灵活性
6. 简化性
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
接下来看个例子
public class Test { public static void main(String[] args) { show(new Cat()); // 以 Cat 对象调用 show 方法 show(new Dog()); // 以 Dog 对象调用 show 方法 Animal a = new Cat(); // 向上转型 a.eat(); // 调用的是 Cat 的 eat Cat c = (Cat)a; // 向下转型 c.work(); // 调用的是 Cat 的 work } public static void show(Animal a) { a.eat(); // 类型判断 if (a instanceof Cat) { // 猫做的事情 Cat c = (Cat)a; c.work(); } else if (a instanceof Dog) { // 狗做的事情 Dog c = (Dog)a; c.work(); } } } abstract class Animal { abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void work() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void work() { 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(num); System.out.println("我是Father 类"); } } class Son extends Father{ int num=20 ; @Override public void print() { System.out.println(num); System.out.println("我是Son 类"); } }
调研成员变量时:
父类的引用只能访问子类空间中属于父类的那块空间
编译时要查看父类中是否有这个属性,没有就编译错误.
运行时访问的是父类的这个成员变量.
调用成员方法时:
编译时要查看父类中是否有这个方法,没有就编译错误.
运行时最终调用的是子类重写父类的方法子类中的方法.
结论:
访问成员变量时 编译和运行 都是看父类中的属性
调用成员方法时 编译看父类 运行看子类
再看一个例子:
public class Demo05 { public static void main(String[] args) { MenZombie menZombie = new MenZombie();//创建一个子类僵尸 menZombie.setLife(10); hitZombie(menZombie); menZombie.setLife(10); hitZombie(new TirZombie(10));//创建一个子类僵尸 } public static void hitZombie(Zombie zombie) { zombie.hit(); } } class Zombie{ private int life; //无参构造 public Zombie() { } //有参构造 public Zombie(int life) { this.life = life; } // 被打的行为 public void hit() { System.out.println("僵尸被打"); } // set get 方法 public void setLife(int life) { this.life =life; } public int getLife() { return life; } @Override//toString public String toString() { return "Zombie [life=" + life + "]"; } } class MenZombie extends Zombie{ @Override//重写父类被打行为 public void hit() { System.out.println(this.getLife()); while (true) { // 掉血 把血量设置为当前血量 -2 this.setLife(getLife()-2); // 打印当前血量 System.out.println("剩余血量"+ this.getLife()); //判断循环结束时间 if (this.getLife()<=0) { System.out.println("门框僵尸挂了"); //结束循环 break; } } } } class TirZombie extends Zombie{ public TirZombie() { // TODO Auto-generated constructor stub } //有参构造 public TirZombie(int life) { this.setLife(life); System.out.println(this.getLife()); } @Override public void hit() { // 出口 if (this.getLife()<=0) { System.out.println("铁桶僵尸挂了"); return;//直接结束这个方法 } // 掉血 把血量设置为当前血量 -2 this.setLife(this.getLife()-5); // 打印当前血量 System.out.println("剩余血量"+ this.getLife()); // 调用自己 this.hit(); } }打印结果
10 剩余血量8 剩余血量6 剩余血量4 剩余血量2 剩余血量0 门框僵尸挂了 10 剩余血量5 剩余血量0 铁桶僵尸挂了