目录
认识多态
- 多态是在继承/实现情况下的一种现象,表现为:对象多态、行为多态。
对象多态可以理解为一个对象有多重形态,而行为多态可以理解为对象的不同行为,下面来看多态的具体代码体现
先定义类:
java
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");
}
}
然后来看多态的具体代码体现:
java
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(),
java
People p1 = new Student();
p1.run();
如果需求变了,或者不好用了,随时可以把代码改成Teacher或者其他,且下面的方法也不用全部重新做大改动。(对象作为组件随时切换)
java
People p1 = new Teacher();
p1.run();
- 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。
例如:
java
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(),那么:
java
People p1 = new Student();
p1.test(); //此时就会报错,无法正常运行
这是因为编译时先看左边的部分,也就是People类中没有test这个方法,它是子类-学生类中独有的 ,所以此时多态下去调用子类的独有功能是不可行的。
如何解决呢?
接下来就要学习多态的类型转换了
多态下的类型转换问题
类型转换
-
自动类型转换::父类 变量名 = new 子类();
javaPeople p = new Teacher();
-
强制类型转换::子类 变量名 = (子类)父类变量;
javaTeacher t = (Teacher)p;
强制类型转换的一个注意事项
- 存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错。
- 但是运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常**(ClassCastException)**的错误出来。
java
People p = new Teacher();
Student s = (Student)p; //java.lang.ClassCastExcepion
强转前,Java建议:
- 使用 instanceof 关键字,判断当前对象的真实类型,再进行强转。
例如:
java
变量名 instanceof Student
假设教师也有一个独有的方法teach(),
java
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
学习自:黑马程序员------JavaSE课程