- 多态即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。(指向父类或者有关系的类。)
//父类=======================================
public class Person {
}
//子类=======================================
public class Student extends Person {
}
//测试类=====================================
import OOP.demo.Person;
import OOP.demo.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
//父类的引用指向子类的对象
Person s2 = new Student();
//同样,作为所有类的“祖宗”,Object也能指向子类的对象
Object s3 = new Student();
}
}
- 在父类中添加一个方法
run
,此时我们可以在测试类中运行s2.run()
:
//父类=======================================
public class Person {
public void run() {
System.out.println("run");
}
}
//子类=======================================
public class Student extends Person {
}
//测试类=====================================
import OOP.demo.Person;
import OOP.demo.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
s2.run();
}
}
====运行结果====
run
-
这里子类继承了父类的方法,所以能够调用
run()
。 -
在子类中重写父类的
run()
方法,稍加修改,在测试类中运行s1.run()
和s2.run()
:
//父类=======================================
public class Person {
public void run() {
System.out.println("run");
}
}
//子类=======================================
public class Student extends Person {
@Override
public void run() {
System.out.println("son"); //重写后改变了输出
}
}
//测试类=====================================
import OOP.demo.Person;
import OOP.demo.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
s1.run();
s2.run();
}
}
====运行结果====
son
son
-
这时子类重写了父类方法,只执行子类的方法。
-
再在子类中添加独有的方法
eat()
,然后在测试类中用s1
和s2
分别调用eat()
。
//父类=======================================
public class Person {
public void run() {
System.out.println("run");
}
}
//子类=======================================
public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}
public void eat() {
System.out.println("eat");
}
}
//测试类=====================================
import OOP.demo.Person;
import OOP.demo.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
s1.eat();
s2.eat(); //报错可修改为`((Student) s2).eat();`
}
}
-
此时
s2.eat();
报错,因为eat()
方法是子类独有的,父类对象无法调用。 -
使用IDEA自动纠正(快捷键:
Alt
+Enter
),会将语句改为:((Student) s2).eat();
,也就是将s2
的引用类型从Person
强制转换为Student
。 -
秦疆老师:对象能执行哪些方法,主要看对象左边的类型,和右边关系不大。
-
多态注意事项:
- 多态是方法的多态,属性没有多态
- 多态存在的条件:
- 有继承关系。类型转换异常:ClassCaseException。说明父子类之间出现了问题。
- 子类重写父类方法
- 父类引用指向子类对象
-
无法重写的方法:
static
修饰的静态方法,属于类,不属于实例。final
修饰的常量,在常量池中。private
修饰的私有方法。