多态性
理解多态性:可以理解为一个事物的多种形态。
何为多态性:对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
多态的使用:虚拟方法调用,有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译,看左边;运行,看右边。
多态性的使用前提: ① 类的继承关系 ② 方法的重写
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
演示:
package cap13;
//Person.java
public class Person {
String name;
int age;
int id = 1001;
public void eat() {
System.out.println("人:吃饭");
}
public void walk() {
System.out.println("人:走路");
}
}
package cap13;
//Man.java
public class Man extends Person{
boolean isSmoking;
int id = 1002;
public void earnMoner() {
System.out.println("男人要赚钱养家");
}
public void eat() {
System.out.println("男人:多吃饭,长肌肉");
}
public void walk() {
System.out.println("男人霸气的走路");
}
}
package cap13;
//Woman.java
public class Woman extends Person{
boolean isBeatury;
int id = 1003;
public void eat() {
System.out.println("女人少吃一点,减肥");
}
public void walk() {
System.out.println("女人优雅的走路");
}
public void useMoney() {
System.out.println("shopping");
}
}
package cap13;
//PersonTest.java
public class PersonTest {
public static void main(String[] args) {
PersonTest personTest = new PersonTest();
personTest.test(new Man());
personTest.test(new Woman());
}
public void test(Person p) {
//虚拟方法调用,有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
p.eat();
//虚拟方法调用,有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
p.walk();
//属性(编译和运行都看左边)
System.out.println(p.id);
}
}
/*
结果:
男人:多吃饭,长肌肉
男人霸气的走路
1001
女人少吃一点,减肥
女人优雅的走路
1001
*/
一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法
虚拟方法调用(多态情况下)子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
编译时类型和运行时类型
编译时p为Person类型,而方法的调用是在运行时确定的,所以调用的是Woman或者Man类 的重写方法。——动态绑定
小结:
方法的重载与重写
重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
多态作用
提高了代码的通用性,常称作接口重用
前提
需要存在继承或者实现关系
有方法的重写
成员方法
编译时:要查看引用变量所声明的类中是否有所调用的方法
运行时:调用实际new的对象所属的类中的重写方法。
编译看左边运行看右边
成员变量
不具备多态性,只看引用变量所声明的类
instanceof操作符
x instanceof A:检验x是否为类A的对象,返回值为boolean型
要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
如果x属于类A的子类B,x instanceof A值也为true。
对象类型转换
- 对Java对象的强制类型转换称为造型
- 从子类到父类的类型转换可以自动进行
- 从父类到子类的类型转换必须通过造型(强制类型转换)实现
- 无继承关系的引用类型间的转换是非法的
- 在造型前可以使用instanceof操作符测试一个对象的类型

练习:
package cap13Exe;
public class InstanceTest {
/*
* 建立InstanceTest 类,在类中定义方法method(Person e);
在method中:
(1)根据e的类型调用相应类的getInfo()方法。
(2)根据e的类型执行:
如果e为Person类的对象,输出: “a person”;
如果e为Student类的对象,输出:
“a student”
“a person ”
如果e为Graduate类的对象,输出:
“a graduated student”
“a student”
“a person”
*/
public static void main(String[] args) {
InstanceTest instanceTest = new InstanceTest();
instanceTest.test(new Student());
System.out.println("=======");
instanceTest.test(new Graduate());
System.out.println("=======");
instanceTest.test(new Person());
}
public void test(Person p) {
p.getInfo();
if(p instanceof Graduate) {
System.out.println("a graduated student");
System.out.println("a student");
System.out.println("a person");
}else if(p instanceof Student) {
System.out.println("a student");
System.out.println("a person");
}else {
System.out.println("a person");
}
}
}
class Person{
public void getInfo() {
System.out.println("Person...getInfo");
}
}
class Student extends Person{
public void getInfo() {
System.out.println("Student...getInfo");
}
}
class Graduate extends Student{
public void getInfo() {
System.out.println("Graduate...getInfo");
}
}
4404

被折叠的 条评论
为什么被折叠?



