Java面向对象(四)

多态

什么是多态

多态:理解一个事物多种形态

比如在现实生活每个人都会扮演着不同的身份,比如张三可以是学生身份,可以是一个孩子身份,可以是教师身份,可以是父亲的身份

Java中多态的体现

子类对象多态性:父类的引用指向子类的对象(或者子类的对象赋给父类引用

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //通过多态的形式,将父类引用指向子类的对象
 4         Person person=new Student();
 5     }
 6 }
 7 
 8 class Person{
 9 
10 }
11 class Student extends Person{
12 
13 }

在多态场景下,调用方法时分为编译时执行时两种。

  ①编译时,认为声明的对象是一个父类的对象实际上生成的是子类对象)看父类有什么属性成员方法成员(即被重写的方法)。

  ②执行时,实际上执行的方法子类重写父类的方法

如果出现子类没有重写相对应的方法时,才会去执行父类的方法

简称:编译看左边,运行看右边

举个例子:

父类:

1 class Person {
2     public void eat() {
3         System.out.println("父亲吃饭");
4     }
5     public void show(){
6         System.out.println("这是一个show方法");
7     }
8 }

子类:

1 class Student extends Person {
2     @Override
3     public void eat() {
4         System.out.println("儿子吃饭");
5     }
6 }

测试类:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //通过多态的形式,将父类引用指向子类的对象
 4         Person person=new Student();
 5         //子类重写了eat方法
 6         person.eat();
 7         //子类没有重写eat方法
 8         person.show();
 9     }
10 }

效果展示:

 执行时先执行子类重写父类的方法,如果没有重写方法才调用父类的方法

多态的缺点

①在使用多态时,子类特有方法会被屏蔽掉的,因为编译的时候父类并没有子类的方法所以是没办法调用的。

②创建子类对象的特有属性和特有方法也会加载到内存中,从而导致内存的浪费

举个例子:

父类:

1 class Person {
2     public void eat() {
3         System.out.println("父亲吃饭");
4     }
5     public void show(){
6         System.out.println("这是一个show方法");
7     }
8 }

子类:

1 class Student extends Person {
2     @Override
3     public void eat() {
4         System.out.println("儿子吃饭");
5     }
6     public void play(){
7         System.out.println("儿子打游戏");
8     }
9 }

测试类:

1 public class Test {
2     public static void main(String[] args) {
3         //通过多态的形式,将父类引用指向子类的对象
4         Person person=new Student();
5         //儿子中独特的play()方法
6         //person.play() 由于父类并没有这个play()方法,所以编译时无法调用play()方法
7     }
8 }

由于父类并没有这个方法,无法调用play()方法

多态的优点

提高代码的维护性,比如一个饲养员有一个饲养的方法,不可能每有一种动态就写一个饲养方法这样不合理,而多态的实现只需要写一个方法里面调用不同对象的方法,代码维护性提高。

提高代码的扩展性,只需要改变每个对象的方法即可,不需要修改饲养员的饲养方法。

多态的前提

多态的两个前提条件是:

  ①存在继承关系:多态是基于继承关系建立的,即一个类可以派生出另一个类。在多态中,存在一个父类和多个子类,子类继承了父类的属性和方法。

  ②存在重写关系:多态要求子类能够重写父类的方法。子类在重写方法时可以根据自己的需求对方法进行不同的实现,从而实现实现多态的效果。

向上转型和向下转型

举个图例:

向上转型

多态就是向上转型:将子类的对象赋值给父类(程序是自动实现的,缺点是失去子类的特有的属性和方法

语法:

父类   对象名  =  new   子类();

向下转型

把父类的对象转为子类的对象(需要强制转换

语法:

子类类型  对象名  =  (子类类型)  父类引用

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //向上转型
 4         Animal animal=new Cat();
 5         //向下转型,需要强制转换
 6         Cat cat = (Cat) animal;
 7         cat.eat();
 8     }
 9 }
10 
11 class Animal{
12 
13 }
14 class Cat extends Animal {
15     public void eat(){
16         System.out.println("小猫吃鱼");
17     }
18 }
19 class Dog extends Animal{
20     public void  eat(){
21         System.out.println("小狗吃骨头");
22     }
23 }

效果展示:

代码上没有任何问题的,但是当两者之间没有继承关系时是没办法强转的,否则会ClassCastException类型转换异常。

 

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //向上转型
 4         Animal animal=new Cat();
 5         Animal animal1=new Dog();
 6         //向下转型,需要强制转换
 7         Dog dog=(Dog) animal;//发现现在编译是没出错哦
 8     }
 9 }
10 
11 class Animal{
12 
13 }
14 class Cat extends Animal {
15     public void eat(){
16         System.out.println("小猫吃鱼");
17     }
18 }
19 class Dog extends Animal{
20     public void  eat(){
21         System.out.println("小狗吃骨头");
22     }
23 }

发现编译时没有任何问题,但是效果展示:

就是因为上面代码中,animal是猫的对象它能变成小狗对象吗?很明显,小猫怎么可能变成小狗对吧。

所以运行时会出现类型转换异常。

instanceof关键字

正因为上面向下转型可能会出现异常,所以这里用到instanceof关键字来判断左边的对象是否为右边的类

语法:

a instanceof A :判断对象a是否为A类的实例
当对象a是类A的实例:返回true
当对象a不是类A的实例: 返回false

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //向上转型
 4         Animal animal=new Cat();
 5         Animal animal1=new Dog();
 6         //向下转型,需要强制转换
 7         if(animal instanceof  Dog){
 8             Dog dog=(Dog) animal;//发现现在编译是没出错哦
 9         }else{
10             System.out.println("animal不是Dog类的实例");
11         }
12     }
13 }
14 
15 class Animal{
16 
17 }
18 class Cat extends Animal {
19     public void eat(){
20         System.out.println("小猫吃鱼");
21     }
22 }
23 class Dog extends Animal{
24     public void  eat(){
25         System.out.println("小狗吃骨头");
26     }
27 }

效果展示:

判断出来animal并不是Dog类的实例所以不会执行

这句代码:Dog dog=(Dog) animal直接输出"animal不是Dog类的实例"

posted @ 2023-11-09 21:05  和哗  阅读(14)  评论(0编辑  收藏  举报