认识多态
- 多态是在继承/实现情况下的一种现象,表现为:对象多态、行为多态。
对象多态可以理解为一个对象有多重形态,而行为多态可以理解为对象的不同行为,下面来看多态的具体代码体现
先定义类:
public class People{ public String name; public int age; public void run{ System.out.println("People"); } } public class Teacher extends People{ public String skill; @Override public void run{ System.out.println("Teacher"); } } public class Student extends People{ public double scores; @Override public void run{ System.out.println("Student"); } }
然后来看多态的具体代码体现:
public class Test{ public static void main(String[] args){ People p1 = new Student(); p1.run(); //“编译看左边,执行看右边” - 解释为:编译时,也就是编写代码时要先给People类 //写上run方法;但是执行时要看左边Student类或者Teacher类的重写之后的run方法。 People p2 = new Teacher(); p2.run(); } }
可以看到,一个People类包含着Student和Teacher,以People类创建出学生对象和教师对象,体现了对象多态;p1调用的run(),实际上是Student重写的run方法,而非People里面的run方法,同样的,p2调用的run()则是Teacher重写的run方法,都是People的行为,但执行的结果不一样,体现了行为多态。
所以我们可以看到,多态的前提:
- 有继承/实现关系;存在父类引用子类对象;存在方法重写。
多态的一个注意事项:
- 多态是对象、行为的多态,Java中的属性(成员变量)不谈多态。
使用多态的好处
在多态形式下,右边对象是解耦合的,更便于扩展和维护。
解耦合:可以理解为一辆玩具车的轮胎可以拆卸,而非焊死在车身上的;一旦轮胎坏了,可以对轮胎进行更换,或者是电池没电了可以更换电池,便于扩展和维护。
与之相反的紧耦合:就是玩具车的轮胎无法拆卸,损坏了就只能更换整辆玩具车了。
例如现在这里写的是Student(),
1. People p1 = new Student(); 2. p1.run();
如果需求变了,或者不好用了,随时可以把代码改成Teacher或者其他,且下面的方法也不用全部重新做大改动。(对象作为组件随时切换)
People p1 = new Teacher(); p1.run();
例如:
public class Test{ public static void main(String[] args){ Student s = new Student(); go(s); Teacher t = new Teacher(); go(t); } public static void go (People p){ } }
多态下会产生的一个问题,怎么解决?
- 多态下不能使用子类的独有功能。
假设学生类中写了一个它自己独有的方法,名为test(),那么:
People p1 = new Student(); p1.test(); //此时就会报错,无法正常运行
这是因为编译时先看左边的部分,也就是People类中没有test这个方法,它是子类-学生类中独有的 ,所以此时多态下去调用子类的独有功能是不可行的。
如何解决呢?
接下来就要学习多态的类型转换了
多态下的类型转换问题
类型转换
- 自动类型转换::父类 变量名 = new 子类();
People p = new Teacher();
- 强制类型转换::子类 变量名 = (子类)父类变量;
Teacher t = (Teacher)p;
强制类型转换的一个注意事项
- 存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错。
- 但是运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastException)的错误出来。
People p = new Teacher(); Student s = (Student)p; //java.lang.ClassCastExcepion
强转前,Java建议:
- 使用 instanceof 关键字,判断当前对象的真实类型,再进行强转。
例如:
变量名 instanceof Student
假设教师也有一个独有的方法teach(),
public static void go(People p){ if(p instanceof Student){ Student s = (Student)p; }else if(p instanceof Teacher){ Teacher t = (Teacher)p; t.teach(); } }
END