1 多态的概述
- 定义:某一类事物的多种存在形态。
- 伪代码如下:
class 动物{} class 猫 extends 动物{} class 狗 extends 动物{} 猫 x = new 猫(); 动物 y = new 猫();
- 猫这类事物既具有猫的形态,又具有动物的形态,这就是对象的多态性。换句话说,就是一个对象对应不同的类型。
- 总结:多态在代码中的体现就是,父类或接口的引用指向其子类的对象,换句话说,就是一个对象两种状态,比如上面的动物 y = new 猫();是不是只有一个对象,但是却有猫和动物的形态。
- 下面以图来讲解多态。(情节纯属虚构)
2 多态的好处
- 动物
package java009; /** * 2017/9/11 * 说明: */ public abstract class Animal { /** * 动物吃饭 */ public abstract void eat(); }
- 猫
package java009; /** * 2017/9/11 * 说明: */ public class Cat extends Animal { @Override public void eat() { System.out.print("猫吃鱼"); } public void sleep(){ System.out.print("猫打瞌睡"); } }
- 狗
package java009; /** * 2017/9/11 * 说明: */ public class Dog extends Animal { @Override public void eat() { System.out.print("狗吃肉"); } public void look(){ System.out.print("狗看门"); } }
- 测试
package java009; /** * 2017/9/11 * 说明: */ public class DuoTai { public static void main(String[] args) { Cat c = new Cat(); DuoTai.method(c); Dog d = new Dog(); DuoTai.method(d); } public static void method(Cat c){ c.eat(); } public static void method(Dog d){ d.eat(); } }
- 点评:貌似上面的代码已经可以实现我们所需要的功能,但是如果此时我们需要增加猪、牛、羊许许多多的动物,哇,太惨,我们在测试类要写很多method的重载方法。很烦,很烦。
package java009; /** * 2017/9/11 * 说明: */ public class DuoTai { public static void main(String[] args) { Cat c = new Cat(); DuoTai.method(c); Dog d = new Dog(); DuoTai.method(d); } public static void method(Animal a){ a.eat(); } }
- 点评:我们通过在method方法中设置method的形参是狗和猫的父类,这样当我们构建对象的时候,无论我们传递什么对象,只要是动物的子类就可以了。
- 多态的好处:提高了代码的扩展性。
3 多态的弊端和前提
- 多态的弊端:不能使用子类特有的功能。
- 多态的前提:
- ①有继承或实现关系。
- ②要有方法的重写。
4 多态的转型
- 向上转型:从子到父,父类引用指向子类对象。
- 弊端:不能访问子类特有的功能。
- 好处:限制对子类特有功能的访问。
- 向下转型:从父到子,父类引用转为子类对象。
- 弊端:可能出出现类转换异常。
- 好处:能对子类特有功能的访问。
- 示例:向上转型
package java009; /** * 2017/9/11 * 说明: */ public class DuoTai { public static void main(String[] args) { Animal a = new Cat(); a.eat(); } }
- 示例:向下转型
package java009; /** * 2017/9/11 * 说明: */ public class DuoTai { public static void main(String[] args) { Animal a = new Cat(); Cat c = (Cat) a; c.eat(); c.sleep(); } }
5 多态的类型判断
- instanceof 用于判断对象的具体类型,只能用于引用数据类型判断。
- 示例:
package java009; /** * 2017/9/11 * 说明: */ public abstract class Animal { /** * 动物吃饭 */ public abstract void eat(); }
package java009; /** * 2017/9/11 * 说明: */ public class Cat extends Animal { @Override public void eat() { System.out.print("猫吃鱼"); } public void sleep(){ System.out.print("猫打瞌睡"); } }
package java009; /** * 2017/9/11 * 说明: */ public class Dog extends Animal { @Override public void eat() { System.out.print("狗吃肉"); } public void look(){ System.out.print("狗看门"); } }
package java009; /** * 2017/9/11 * 说明: */ public class DuoTai { public static void main(String[] args) { method(new Cat()); } public static void method(Animal a){ if(a instanceof Cat){ Cat c = (Cat) a; c.sleep(); c.eat(); }else if(a instanceof Dog){ Dog d = (Dog) a; d.eat(); d.look(); } } }
6 多态的成员变量--了解
- 示例:
package java009; /** * 2017/9/12 * 说明: */ class Fu{ int num = 3; } class Zi extends Fu{ int num = 4; } public class Test { public static void main(String[] args) { Zi z = new Zi(); System.out.println(z.num); Fu f = new Zi(); System.out.println(f.num); } }
- 编译时,参考引用型变量所属的类中是否有调用的成员变量,有,则编译通过,没有,则编译失败。
- 运行时,参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
- 温馨小提示:实际开发中,不可以这样定义的,以为我们一般会将属性私有化,提供对外的setter和getter方法。
7 多态的成员函数
- 示例:
package java009; /** * 2017/9/12 * 说明: */ class Fu{ public void show(){ System.out.print("fu"); } } class Zi extends Fu{ public void show(){ System.out.print("zi"); } } public class Test { public static void main(String[] args) { Fu f = new Zi(); f.show(); } }
- 编译时,参考引用型变量所属的类中是否有调用的函数,有,则编译通过,没有,则编译失败。
- 运行时,参考的是对象所属的类中是否有调用的函数。
8 多态的静态函数
- 示例:
package java009; /** * 2017/9/12 * 说明: */ class Fu{ public static void show(){ System.out.print("fu"); } } class Zi extends Fu{ public static void show(){ System.out.print("zi"); } } public class Test { public static void main(String[] args) { Fu f = new Zi(); f.show(); } }
- 编译时,参考引用型变量所属的类中是否有调用的静态方法。
- 运行时,参考引用型变量所属的类中是否有调用的静态方法。