Java三板斧—多态

目录

1、前言

2、多态

2.1 多态的概念

2.2 多态实现条件

 2.3 重写

2.3.1 重写的概念

2.3.2 重写规则

2.3.3 重写和重载的区别

2.3.4 动态/静态绑定

2.4  向上转型

2.4.1 概念

2.4.2 使用场景

 2.4.3 特点

3、结语

 


1、前言

因为继承与多态的内容和知识点较多,所以我们放在两次blog中来讲解,这次我们重点来了解一下多态,相信有继承基础的你,这根本不是难事,如果你对继承没有什么概念,请参考我上一篇博客“Java三板斧—继承”。

2、多态

2.1 多态的概念

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

  • 同样都是父类中吃的方法,猫就是吃猫粮,狗就是吃狗粮,同一个方法,因为对象的不同,产生不同的效果,这就是多态。 

2.2 多态实现条件

在java中要实现多态,必须要满足如下几个条件,缺一不可:
1. 必须在继承体系下,完成向上转型
2. 子类必须要对父类中方法进行重写
3. 通过父类的引用调用重写的方法
多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法,我们分点来介绍,首先看下面这个例子:

class Animal{
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println(name +" 正在吃饭!(Animal)");
    }
}
class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
         System.out.println(name +" 正在吃狗粮");
    }
}
class Bird extends Animal{
    public String wing;
    public Bird(String name, int age) {
        super(name, age);
    }

   public void fly() {
        System.out.println(getName()+" 正在飞!");
    }

    @Override
    public void eat() {
        System.out.println(name +" 正在吃鸟粮");
    }
}

///分割线//
public class Main {
// 编译器在编译代码时,并不知道要调用Dog 还是 Cat 中eat的方法
// 等程序运行起来后,形参a引用的具体对象确定后,才知道调用那个方法
// 注意:此处的形参类型必须时父类类型才可以
    public static void eat(Animal a){
        a.eat();
    }
    public static void main(String[] args) {
        Bird bird = new Bird("鹦鹉",2);
        Dog dog = new Dog("狗子", 1);
        eat(bird);
        eat(dog);
    }
}

下面画图讲解一下,什么是多态。

  • 在上述代码中, 分割线上方的代码是 类的实现者 编写的, 分割线下方的代码是 类的调用者 编写的.
  • 当类的调用者在编写 eat 这个方法的时候, 参数类型为 Animal (父类), 此时在该方法内部并不知道,也不关注当前的a 引用指向的是哪个类型(哪个子类)的实例此时 a这个引用调用 eat方法可能会有多种不同的表现(和 a 引用的实例相关),,这种行为就称为 多态。

 2.3 重写

2.3.1 重写的概念

  • 重写(override):也称为覆盖。
  • 重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据对象的需要,定义特定于自己的行为。 也就是说子类能够根据需要实现或者叫做改写父类的方法。
  • 上述代码中的eat就是重写,调用两个对象的时候,都执行的是bird和dog中的eat方法,也就是对父类Animal中eat方法的重写。

2.3.2 重写规则

  1. 子类在重写父类的方法时,一般必须与父类方法原型一致:修饰符 返回值类型 方法名(参数列表) 要完全一致;
  2. 被重写的方法返回值类型可以不同,但是必须是具有父子继承关系的;
  3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected;
  4. 父类被static、private修饰的方法、构造方法都不能被重写。
  5. 重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验,例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写。

2.3.3 重写和重载的区别

区别 重载 重写
参数列表 必须修改 不能修改
返回类型 可以修改 不能修改
访问限定符 可以修改 子类要大于父类的访问修饰符等级

.图片的形式更加方便理解:

1、重写

2、重载

2.3.4 动态/静态绑定

1、静态绑定:

也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表:方法重载

2、动态绑定:

也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用哪个类的方法。典型代表:方法重写。

2.4  向上转型

2.4.1 概念

  • 向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
  • 语法格式:

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

1、向上转型方法1:

2、向上转型方法2(简写) :

2.4.2 使用场景

1、直接转型:子类对象直接赋给父类

2、方法的传参: 

        理论上main函数中的function要传Animal类型的对象,实际上传递了它的子类bird,这里使用了简写(向上转型方法2,2.4.1的第2点),也可以新建一个对象,传入这个对象

 3、Bird作为返回值给到Animal。 

       方法的返回值:本来返回值是Animal类型的,现在返回一个它的子类,就是发生了向上转型。

 2.4.3 特点

        发生向上转型之后,animal是Animal类的(是父类),只能调用父类中独有的方法,不能调用子类中的方法; fly是Bird类中的独有方法,animal是Animal类的,不能访问Bird类中的fly方法了。

3、结语

至此,我们就介绍完了Java的第二板斧,继承与多态,第三板斧—抽象类与接口即将揭开神秘面纱,期待大家的三连。

        

猜你喜欢

转载自blog.csdn.net/weixin_44580000/article/details/124947055