前言
在前篇文章中我们讲解了Java三大特性之一的继承性,本篇文章中我们将继续对面向对象编程的学习,了解并学习最后一个特性——多态性。
一、多态
(1)什么是多态
多态:指的是对象的多态性,同一对象在不同时刻表现出来的不同形态。
例如:猫
我们可以说猫是猫:猫 cat = new 猫();
也可以说猫是动物:动物 animal = new 猫();
这里猫在不同的时刻表现出来了不同的形态,就是多态。
(2)程序中的多态
多态的前提:
- 有继承或者实现关系
- 有方法重写
- 父类引用指向子类对象(或子类的对象赋值给父类的引用)
实现关系:后面会学习接口(interface),类和接口就是实现关系,类实现接口。
实现关系也可以看成是继承关系
3)多态示例
就上文提到的“猫是猫”,“动物是猫”来看:
父类Animal:
public class Animal {
public void eat() {
System.out.println("吃东西");
}
}
子类Cat:
public class Cat extends Animal{
@Override
public void eat() {//子类重写父类方法
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
测试类ClassTest:
public class ClassTest {
public static void main(String[] args) {
//正常使用:
Animal animal = new Animal();
animal.eat();
Cat cat1 = new Cat();
cat1.eat();
cat1.catchMouse();
System.out.println("----------")
//多态:
Animal animal2 = new Cat();//父类引用指向子类对象(或子类的对象赋值给父类的引用)
animal2.eat();//执行Animal类的eat方法,还是执行Cat类的eat方法
animal2.catchMouse();//此处会报错
}
}
上面的Animal animal2 = new Cat();就是多态的体现,猫可以被当做动物来看待。
animal2.eat();这就是多态的使用。虽然猫可以当做动物来看待,但真正执行方法的时候,还是执行子类的方法。
animal2.catchMouse();会报错,当把猫当动物看的时候,编译器会查看动物类是否有catchMouse方法,发现没有,就会报错。
(4) 多态中成员访问的特点
看如下代码:
父类Animal:
public class Animal {
int a = 20;
public void eat() {
System.out.println("吃东西");
}
}
子类Cat:
public class Cat extends Animal{
int a = 100;
int b = 200;
@Override
public void eat() {//重写父类的方法
System.out.println("猫吃鱼");
}
public void catchMouse() {//子类独有的方法
System.out.println("猫抓老鼠");
}
}
测试类ClassTest:
public class ClassTest {
public static void main(String[] args) {
//正常使用:
Animal animal = new Animal();
animal.eat();
Cat cat1 = new Cat();
System.out.println(cat1.a);
System.out.println(cat1.b);
cat1.eat();
cat1.catchMouse();
System.out.println("--------------");
//多态:
Animal animal2 = new Cat();//父类引用指向子类对象(或子类的对象赋值给父类的引用)
System.out.println(animal2.a);
// System.out.println(animal2.b);//会报错
animal2.eat();//执行Cat类的eat
// animal2.catchMouse();//此处会报错。
}
}
回顾:Java代码运行的流程
成员 | 编译期 | 运行期 |
---|---|---|
实例变量 | 看等号左边(即父类) | 看等号左边(即父类) |
实例方法 | 看等号左边(即父类) | 看等号右边(即子类) |
即 编译看左边,运行不一定看右边!
为什么实例变量和实例方法的访问不一样呢?
因为实例方法有重写,实例变量没有。
(5)多态的好处和弊端
好处:提高了程序的扩展性,容易设计出通用的代码。
弊端:屏蔽了子类独有的功能。(不过,可以强转类型)
总结
总的来说:多态用最简单的一句话来解释——父类型的引用指向子类型的对象。用一句比较通俗的话:同一操作作用于不同的对象,可以产生不同的效果。这就是多态。最后再强调需要注意的几点:
- 多态情况下,子父类存在同名的成员变量时,访问的是父类的成员变量。
- 多态情况下,子父类存在同名的非静态的成员函数时,访问的是子类的成员函数。
- 多态情况下,子父类存在同名的静态的成员函数时,访问的是父类的成员函数。
- 多态情况下,不能访问子类特有的成员。
那么我们本次学习内容到这里就结束了,下一篇我们将开始java中另一个重要知识点——接口的学习。感谢大家观看。