> 文档中心 > 多态(polymorphism)

多态(polymorphism)


多态

  • 多态:不同的对象调用同一个方法可能会产生不同的行为
package com.chenxingen;class Pet{    String name;//宠物名    public Pet() {    }    public Pet(String name) { this.name = name;    }    public void eat(){ System.out.println("吃东西...");    }}class Cat extends Pet{//猫类    public void eat(){ System.out.println("猫吃鱼...");    }}class Horse extends Pet{//马类    public void eat(){ System.out.println("马吃草...");    }}public class Work241 {    //多态    //使用父类作为方法形参    public static void petEat(Pet pet){ pet.eat();    }    public static void main(String[] args) { //子类到父类的自动转型 Pet cat=new Cat(); Horse horse=new Horse(); petEat(cat); petEat(horse);    }}

注意:多态指的是方法,属性没有多态这个概念

多态存在的必要条件:

  1. 继承
    首先我们要知道多态的概念,是同一个方法,不同的对象调用会有不同的行为,也就是说不同的对象都必须要有这个同一的方法,显然,如果我们每个都自己定义一个名字相同的方法,是能够做到的,但显然不符合代码的复用性,而多态的存在就是提高代码的复用性,所以我们需要继承,只需要父类中有这个方法,其所有的子类都会有,所以多态存在的第一步必须要继承!
  2. 方法重写
    我们已经实现里多态的第一步,继承!我们知道,我们继承下来的方法都是父类中的,父类写好的方法是不变的,这个时候我们的子类如果不进行重写该方法,那么尽管是不同的对象,当执行该方法的时候,其产生的行为还是一模一样,所以我们必须在子类继承有该方法的父类后,还要对该方法进行重写
  3. 父类引用指向子类
    这个地方需要我们重点理解!!!(下面我们从便于理解的角度来阐述这一点)

如下示例代码中:

public class Work241 {    //多态    //使用父类作为方法形参    public static void petEat(Pet pet){ pet.eat();    }    public static void main(String[] args) { //子类到父类的自动转型 Pet cat=new Cat(); Horse horse=new Horse(); petEat(cat); petEat(horse);    }}

我们知道Pet是父类,cat、horse是子类;

Pet cat=new Cat();

这行代码的意思就是:创建一个猫对象,用一个宠物类型的变量类接收,从逻辑上,可以接受!

也就是说:猫是宠物


Cat cat=new Pet();   ×

这行代码的意思就是:创建一个宠物对象,用一个猫类型的变量类接收,从逻辑上,可以接受,但是有歧义,因为宠物不一定就是猫!

而机器语言与自然语言不同,java又是一门严谨的语言,所以这种写法错误!

 public static void petEat(Pet pet){ pet.eat();    }petEat(cat);

这个理解起来应该没有问题,因为本身也是一个Pet类型的变量接受!


Horse horse=new Horse();petEat(horse);

这个理解起来可能会有些一些问题,因为我们是用Horse变量类型来接受的,而方法中的形参是Pet类型的,两者不一样,但是还是那句话,我们把马当做宠物是完全没有问题的,所以可以这样使用,这种就叫自动类型转换,这也叫做父类引用指向子类对象

Cat cat=new Pet();

cat父类引用,new Pet()子类对象


上述就叫多态,可以看出,这样我们能够大大的提高代码的复用性,如何看出,可以比较

public static void petEat(Pet pet){ pet.eat();    }等于    public static void petEat(Cat cat){ cat.eat();    }    public static void petEat(Horse horse){ horse.eat();    }     public static void petEat(... ...){ ....eat();    }

如果不适用多态,随着宠物类型的增多,我们的方法会逐渐增加,代码趋于繁琐…


补充:多态中常犯错误!!!

eg;(编译问题)

在这里插入图片描述
seeDoor方法是子类Dog特有的方法,不是重写的方法
多态(polymorphism)
此时,我们可以看到,编译报错了!

这是因为在编译的时候,是检查语法错误,而此时new Dog()是用一个动物变量来接受,这并没有错误,但是,在执行dog.seeDoor()时,报错了,因为dog是一个Animal变量,编译器需要去Animal类中查看是否存在一个叫seeDoor的方法,我们知道seeDoor方法是Dog类特有的,在Animal中没有,所以编译器报错了!

那如何处理这种情况呢?

多态(polymorphism)
使用强转即可!

eg;(运行问题)

在这里插入图片描述
我们创建里一个Dog对象,用Animal类型接收,然后将其强转为Dog类型,强转为Cat类型,都没有错误

因为动物可以是猫,也可以是狗,就像猜盲盒一样,我们知道这个盒子里要么是猫要么是狗,只有打开后,观察其特征,我们才知道其具体是啥,但是我们现在没有具体看到,只知道要么是猫,要么是狗,我们这样去说并没有错,也就是编译检查为什么通过的原因!
在这里插入图片描述
问题来了,报错了,运行报错了,盒子打开了,我们知道有人猜错了,有人猜对了,那么我们现在再把盒子关闭,人们都知道里面是狗了!

为里防止这种情况,我们需要借助工具

Instanceof

Pet pet=new Cat(); System.out.println(pet instanceof Pet);//TRUE System.out.println(pet instanceof Cat);//TRUE System.out.println(pet instanceof Horse);//FALSE

Instanceof是二元运算符,左边是对象,右边是类:当对象是右边类或者子类所创建对象时,返回true