多态
- 定义:一类事物存在多种形态
- 示例:
动物中的猫、狗
猫A这个具体对象对应的类型是猫类型
猫 猫A=new 猫();
同时猫类型也是一种动物类型,所以也可以把猫A称为动物
动物 猫A=new 猫();
动物是猫和狗的具体事物抽象出来的父类型
上面的就是:父类型引用指向了子类对象(多态的体现) - 多态的典型使用
package com.bixiangdong.oop;
abstract class Animal{
//动物都有吃的功能
abstract void eat();
}
class Dog extends Animal{
@Override
void eat() {
System.out.println("狗吃骨头");
}
}
class Cat extends Animal{
@Override
void eat() {
System.out.println("猫吃鱼");
}
}
public class Demo06 {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
//猫吃鱼
//狗吃骨头
}
//调用猫的吃的功能
// public static void method(Cat cat){
// cat.eat();
// }
//调用狗的吃的功能
// public static void method(Dog dog){
// dog.eat();
// }
//此时我们发现是动物都有吃的功能,能不能传递一个动物(不管是猫或者狗)进来就可以调用吃的功能呢
public static void method(Animal animal){
animal.eat();
}
}
- 多态的优点
- 提高了代码的扩展性,前期定义的代码可以使用后期的内容
- 多态的缺点:
- 前期定义的功能不能使用后期子类特有的功能(在父类(接口)中没有)
- 多态的前提:
- 类与类之间需要建立关系,继承或者实现
- 要重写父类(接口)中的功能
- 向上转型:限制子类对象对特有功能的访问
Animal cat = new Cat();
- 向下转型:使用子类对象中的特有功能
Animal cat = new Cat();
Cat cat1=(Cat)cat;
- 对于转型:是对于子类对象在做转型的操作
父类引用指向子类对象
- 子类对象中有的方法 就会调用子类对象的方法
- 子类对象中没有的方法就调用父类中的方法
- 子类特有的方法 只能是子类类型的引用才能够调用
package com.bixiangdong.oop;
class Fu2{
void work(){
System.out.println("Fu2 上班");
}
void read(){
System.out.println("Fu2 看报纸");
}
}
class Zi2 extends Fu2{
void work(){
System.out.println("Zi2 上学");
}
void run(){
System.out.println("Zi2 跑步");
}
}
public class Demo07 {
public static void main(String[] args) {
Fu2 zi2 = new Zi2();
zi2.work();//子类对象中有的方法 就会调用子类对象的方法
zi2.read();//子类对象中没有的方法就调用父类中的方法
//Zi2 上学
//Fu2 看报纸
Zi2 zi21=(Zi2)zi2;
zi21.run();//子类特有的方法 只能是子类类型的引用才能够调用
}
}
instanceof 用于判断对象的具体类型
- 用法(仅仅介绍怎么使用)
多态时访问成员的特点
-
成员变量
- 编译时:参考引用类型变量所属的类中是否有调用的成员变量,有,编译通过;没有,编译失败
- 运行时:参考引用类型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量
- 总结:编译和运行都看左边
-
成员函数(非静态)调用依赖于对象
- 编译时:参考引用类型变量所属的类中是否有调用的成员函数,有,编译通过,没有,编译失败
- 运行时:参考的是对象所属的类中是否有调用的函数,并运行该类中的函数
- 总结:编译时看左边,运行时看右边
-
静态函数 调用不依赖于对象,类名调用即可
- 编译时:参考引用类型变量所属的类中是否有调用的静态函数,有,编译通过;没有,编译失败
- 运行时:参考引用类型变量所属的类中是否有调用的静态函数,并运行该所属类中的静态函数
- 总结:编译和运行都看左边
-
成员函数