多态:可以理解为事物存在的多种体现形态
如:人:男人,女人
动物:猫,狗,鸟
猫这个动物应该是猫类型的:猫 cat = new 猫();
同时猫也是动物的一种:动物 y = new 猫(); 动物是猫和狗具体事物抽取出来的父类型,父类型指向了子类对象
1、多态的体现
父类的引用指向了自己的子类对象
父类的引用也可以接收自己的子类对象
2、多态的前提
必须是类与类之间有关系,要么继承,要么实现
还有一个前提:存在覆盖
3、多态的好处
多态的出现大大的提高了程序的扩展性
4、多态的弊端
虽然提高了扩展性,但是只能使用父类的引用访问父类中的成员
5、多态的应用
6、多态使用的注意事项
看一个关于多态的例子:
1 abstract class Teacher 2 { 3 public abstract void teach(); 4 public void sleep() 5 { 6 System.out.println("睡觉"); 7 } 8 } 9 class MathTeacher extends Teacher 10 { 11 public void teach() 12 { 13 System.out.println("教数学"); 14 } 15 } 16 class ChineseTeacher extends Teacher 17 { 18 public void teach() 19 { 20 System.out.println("教语文"); 21 } 22 public void sleep() 23 { 24 System.out.println("睡觉在沙发上"); 25 } 26 } 27 //将代码进一步优化,定义一个工具类,这样就不需要实例化每一个老师对象,直接调用工具类,然后把各种类型的Teacher传进去既可 28 class TeachTest 29 { 30 public static void teach(Teacher t)//Teacher t类型是Teacher由于多态可以直接传MathTeacher等 31 { 32 t.teach(); 33 t.sleep(); 34 } 35 } 36 class Test 37 { 38 public static void main(String[] args) 39 { 40 /* 41 实例化一个新的数学老师 42 Teacher t = new MathTeacher(); 类型提升,向上转型 43 t.sleep(); 44 如果想要调用猫的特有方法该怎么做? 45 强制将父类引用转成子类类型,向下转型 46 MathTeacher mt = (MathTeacher)t; 47 mt.teach(); 就可以调用数学老师里面的教学方法 48 */ 49 /* 50 如果要调用类的方法,先实例化一个类,然后分别调用 51 MathTeacher mt = new MathTeacher(); 52 mt.teach(); 53 mt.sleep(); 54 ChineseTeacher ct = new ChineseTeacher(); 55 ct.teach(); 56 ct.sleep(); 57 发现这样比较麻烦,向上抽取,定义一个新的工具类TeachTest,将方法封装进去 58 */ 59 TeachTest tt = new TeachTest(); 60 tt.teach(new MathTeacher()); 61 tt.teach(new ChineseTeacher()); 62 } 63 }
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,编译失败
在运行时期:参阅对象所属的类中是否有调用的方法
简单总结:成员函数在多态调用时,编译看左边,运行看右边
(面试)在多态中成员变量,静态成员函数的特点:
无论编译或运行,都参考左边(引用型变量所属的类)
如:
1 Fu f = new Zi(); 2 System.out.println(f.num);//打印的是父类里面的变量num 3 Zi z = new Zi(); 4 System.out.println(z.num);//打印的是子类里面的变量num 5 //静态的方法也是一样。
一个集合了接口,多态的例子
1 /* 2 类 主板,主板有运行方法run() 3 一段时间后想要上网 加入网卡类 4 想要听音乐 加入 声卡类 5 6 但是这样一个一个的加入使得代码的扩展性很差,每次都要重新修改很多代码 7 8 于是引入一个通用的接口PCI类 9 所有设备都有打开和关闭功能 10 让网卡和声卡分别取实现PCI接口,重写成自己的打开和关闭功能 11 12 给主板加上一个实现pcirun的方法,传递参数的值为PCI类型的 13 可以利用多态PCI p = new NetCard(); 14 15 所以在下面主函数中运行时 创建新的主板对象以后 16 mb.pcirun(new NetCard()); 17 mb.pcirun(new SoundCard()); 18 就可以分别使用网卡和声卡了,如果以后还要再加入比如显卡 19 就只需要建立一个显卡类去实现PCI接口,然后直接用主板中的pcirun方法就可以了。 20 21 */ 22 class MainBoard 23 { 24 public void run() 25 { 26 System.out.println("mainboard run"); 27 } 28 public void pcirun(PCI p) 29 { 30 p.open(); 31 p.close(); 32 } 33 } 34 interface PCI 35 { 36 public abstract void open(); 37 public abstract void close(); 38 } 39 class NetCard implements PCI 40 { 41 public void open() 42 { 43 System.out.println("netcard open"); 44 } 45 public void close() 46 { 47 System.out.println("netcard close"); 48 } 49 } 50 class SoundCard implements PCI 51 { 52 public void open() 53 { 54 System.out.println("SoundCard open"); 55 } 56 public void close() 57 { 58 System.out.println("SoundCard close"); 59 } 60 } 61 class Test 62 { 63 public static void main(String[] args) 64 { 65 MainBoard mb = new MainBoard(); 66 mb.run(); 67 mb.pcirun(new NetCard()); 68 mb.pcirun(new SoundCard()); 69 } 70 } 71 /* 72 这样做的好处: 73 大大的降低了主板和各种独立设备直接的耦合性 74 中间用一个PCI接口来连接起来 75 程序日后非常方便扩展 76 */