Java零基础入门-多态

一、概述

我之前上几期是教学了java类、及面向对象编程的三大基本特性,封装继承和多态。前一期,我是把继承大致讲了一遍,不知道你们对它有没有理解,何为继承,继承有啥好处,可以多继承嘛?等这类问题,我在上一期内容都有讲解,如果你们答不出来,没关系,你们可以再回去瞅瞅。

而这一期,我们要来学习一个新概念--多态,是继封装、继承之后,面向对象的第三大特性。好的,废话不多说,咱这就开始。

二、本期教学目标

  • 何为多态?
  • 实现多态的前提条件?
  • 如何实现多态?
  • 多态有何优劣?
  • 什么是向上转型和向下转型?
  • 多态实例演示
  • ...

三、正文

1️⃣概述

说起多态,你们从字面意思上肯定无法理解,没关系,我给大家讲个与生活息息相关的例子,比如啊,对于吃饭这个动作,人是用手用筷子,鸡是嘴琢,鱼是用嘴吸,对于跑这个动作,人跑、鸟跑、猫跑、鸵鸟跑等都是不一样的,对于飞这个动作,飞机、鸟、大雁、飞鱼等展示形式也是不一样的。虽然行为都是一样,但通过不同的事物,对于行为的具体表现都是不一样的,这就是多态。多态,形容的就是这种对于同一行为却表现出多种形态的现象。

2️⃣定义

多态:准确来说,是指对同一行为,对于不同的对象有具体表现不同形式。而对于对象多态,表示对同一方法,不同对象具有不同的实现方法形式。

3️⃣前提条件

要实现多态,那它有那些前提呢?

  • 继承或者实现。
  • 实现方法重写。
  • 父类引用指向子类对象或者接口引用指向实现类对象。

4️⃣多态优劣

那对于多态而言,有何优势又有何劣势呢?这点我分开给大家逐一讲解一下。

  1. 优势:在实际开发过程中,父类类型作为方法形式参数,传递给子类方法,进行方法调用,更能体现出多态的可拓展性与便利性
  2. 劣势:多态情况下,只能调用父类的共性内容,不能调用子类特有的内容(方法、属性等)

5️⃣实现多态

如下实现多态?多态往往体现在父类的引用指向它的子类,比如:

java 复制代码
父类类型 变量名 = new  子类对象;

变量名.方法名();

6️⃣向上转型

为何要说到这个概念呢?这也是为了弥补因为多态这个特点而导致用父类变量接收子类对象之后,就不能调用子类所特有的方法了(父类没有)这个小问题,所以就需要向上转型,当左边变量类型大于右边对象变量类型,将该过程就成为向上转型,比如:

java 复制代码
// 向上转型  
Animal dog = new Dog();  

此时,dog对象按编译时按照左边变量类型(Animal)处理,就只能调用父类(Animal)中有的变量和方法,而不能调用子类特有的变量和方法了。

大家请看:

java 复制代码
public class Dog extends Animal{//子类

    private String active;

    @Override
    public void eat(){
        System.out.println("我是狗狗,吃骨头!");
    }

    public void run(){
        System.out.println("我是狗狗,我会跑!");
    }

    public static void main(String[] args) {

        Animal dog = new Dog();
        dog.eat();
    }

}

dog对象是无法调用自身的run()方法和自定义的属性。

7️⃣向下转型

所以对于有向上转型,就有向下转型,相反,向下转型就是当左边变量类型小于右边变量类型,我们就称为向下转型。此刻,编译期间,按照左边变量类型处理,就可以调用子类特有的方法和属性了。比如:

java 复制代码
    public static void main(String[] args) {

        Animal dog1 = new Dog();
        dog1.eat();
        
        if (dog1 instanceof Dog){

            Dog dog2 = (Dog)dog1;  //向下转型
            dog2.run();        // 调用的是Dog的run()方法
        }
    }

解释一下:为了避免ClassCastException异常,Java有专门提供 instanceof 关键字,作用就是给引用变量做类型校验,只要用instanceof判断如果返回true,那么强转为该类型就一定是安全的,借此也不会报ClassCastException异常。

四、实例演示

接下来我给大家举个例子,重点演示一下。

先来定义一个父类。

java 复制代码
@Data
public class Animal {//父类

    private String type;
    private String name;
    private String color;

    public void eat() {
        System.out.println("我是父类,吃东西!");
    }
    
}

然后再来定义个子类Dog。

java 复制代码
@Data
public class Dog extends Animal {//子类

    private String active;

    @Override
    public void eat() {
        System.out.println("我是狗狗,吃骨头!");
    }

    //独有功能
    public void lockHome() {
        System.out.println("我是狗狗,我会看家");
    }
}

大家可以看到,dog2对象可以调用Dog类的lockHome()方法,该dog1是无法调用的,但dog2可以调用,这就是向下转型所致。

总结:

  • **成员变量:**只看编译时类型, 成员变量没有重写。访问的是父类的成员变量。
  • **非虚方法:**只看编译时类型,也就是访问的是父类中的方法。
相关推荐
丑小鸭是白天鹅5 分钟前
Kotlin协程详细笔记之切线程和挂起函数
开发语言·笔记·kotlin
ChillJavaGuy12 分钟前
常见限流算法详解与对比
java·算法·限流算法
sali-tec14 分钟前
C# 基于halcon的视觉工作流-章34-环状测量
开发语言·图像处理·算法·计算机视觉·c#
java搬砖工-苤-初心不变15 分钟前
基于 lua_shared_dict 的本地内存限流实现
开发语言·junit·lua
寻星探路19 分钟前
数据库造神计划第六天---增删改查(CRUD)(2)
java·大数据·数据库
毕设源码-朱学姐36 分钟前
【开题答辩全过程】以 4S店汽车维修保养管理系统为例,包含答辩的问题和答案
java·spring boot·汽车
charlie11451419137 分钟前
Kotlin 的 apply / with / run 详解
开发语言·kotlin·程序设计·面对对象
Tiger_shl42 分钟前
【层面一】C#语言基础和核心语法-02(反射/委托/事件)
开发语言·c#
GW_Cheng1 小时前
分享一个vue2的tinymce配置
开发语言·javascript·ecmascript
路人与大师1 小时前
【Mermaid.js】从入门到精通:完美处理节点中的空格、括号和特殊字符
开发语言·javascript·信息可视化