由继承到多态

回顾一些之前学过的知识:Java面向对象的特征是什么?

——封装、继承、多态

封装:set、get方法

继承:extends、implements关键字

在上一章内容中我们提到了继承,但当子类从父类中继承了各种属性和方法后。是否就一定要像父类一样表现为同一种状态呢?对于同一种方法,父类和子类一定会是同一种执行结果吗?

多态,从名字中我们可以获取到什么信息?多种状态、不一样的状态

目录

一、从继承到多态

1.现象引入

2.什么是多态

3.多态的作用

二、转型

1.数据类型

2.基本数据类型的转型

1)强制转型

2)自动转型

3)转型的推广

3.创建对象与内存地址

1)对象是如何被创建的

2)什么是内存地址

3)代码阶段

三、代码示例


一、从继承到多态

1.现象引入

假设:K是一名大学生

什么是多态:K作为大学生中一个具体的对象,K可以被称为大学生,也可以同时被称为学生,两种身份。

即一个对象拥有两重身份,使用这两个身份有什么区别吗?

大学生作为K的身份明显更为具体,而学生则更为笼统(抽象)。

思考:物理中的物态变化是否和Java中的多态有相似之处?(“态”之间的变化)

2.什么是多态

用一句话来概述:同一方法在不同情况下具有不同的行为。

多态是面向对象编程中一个重要的概念,它允许不同类的对象对同一个消息作出不同的响应。

在Java中,多态性通过方法重写(override)和方法重载(overload)实现。

方法重写是运行时多态的体现,它发生在子类重写父类方法的情况下。

由于Java的动态绑定机制,在运行时会根据对象的实际类型调用相应的重写方法,这就是多态的表现。即使是通过父类引用指向子类对象,调用的方法仍然是子类实现的方法。

通过多态性,我们可以编写更灵活的代码,减少重复的代码量,提高代码的可扩展性和可维护性。多态性使得代码更具有通用性,能够适应不同类型的对象。

3.多态的作用

多态的作用之一:可以避免if else的判断(减少if else判断条件的使用)

多态可以实现匹配机制(相同的方法,不同的结果)

二、转型

转型是实现多态性的手段之一。

1.数据类型

数据类型 = 基本数据类型+引用数据类型(如类、接口、数组等等)

2.基本数据类型的转型

1)强制转型

例:一个浮点数 → 一个整数(有缺点:损失精度)

Double d = 1.22;

Int i = (int)d;

2)自动转型

例:一个整数 → 一个浮点数

int i = 10;

double j = i;

注意:强制转型前需要(),而自动转型则不需要。

3)转型的推广

A a = new A;

B b = a ; (什么情况下该式成立?)

—— 假设1.0:A为学生类,B为大学生类

现在A创建了一个新的对象学生a,那么要将学生a的值赋给B的一个对象大学生b,是否成立且合理呢?

大学生b = 学生a;

理解:即学生是否一定是一个大学生?(按照顺序从右往左理解,赋值的规则)

—— 假设2.0:B为学生类,A为大学生类

学生a =大学生b ;

理解:即大学生是否一定是一个学生?

显然是假设2.0成立(引用数据类型中的自动转型),从而B为A的父类

可以类比数学中放缩的思想:大学生对象可以是大学生,也可以是学生

3.创建对象与内存地址

在转型的推广中,我们需要用到创建对象的相关知识,在这里我们进行一些回顾。

1)对象是如何被创建的

子类创建对象时,先在内存中开辟一片空间,存入,然后再将内存的地址返回给对象变量名去存储。

所以,对象的地址一般会存在子类类型对应的对象变量名中

A a = new A( );   

a为对象变量名,对象又是存储在内存中具体的数据体

2)什么是内存地址

示例1:

package lzc20240415.多态;

public class Test {
    public static void main(String[] args){
        Test test = new Test();
        System.out.println(test);
    }
}

输出:

lzc20240415.多态.Test@7ba4f24f

@xxxxxx后面那一串可以暂且认为是地址

示例2:

package lzc20240415.多态;

public class Student {
}

class uniStudent extends Student{
}

class Main{
    public static void main(String[] args){
        uniStudent uniStu = new uniStudent();
        System.out.println(uniStu);
        Student stu = uniStu;
        System.out.println(stu);
    }
}

输出:

lzc20240415.多态.uniStudent@7699a589

lzc20240415.多态.uniStudent@7699a589

子类对象的引用地址也可以存储在父类的对象变量名中

3)代码阶段

编译期

1.0判断哪些变量可以调用哪些属性和方法(不会运行)

2.0查找类的代码结构,若类中有定义则可以通过编译

     若无则无法通过(会变红报错)

运行期

未转型前应是:Student stu = new Student( );

只有一个uniStu对象(子类对象可以通过赋值给父类引用)

其中重写的方法会覆盖父类中同名的方法

——K对外声称他是一名学生,但并不妨碍他是一名大学生,他可以具有阅读高等数学表现行为(可以调用方法,合理)

三、代码示例

public class Student { //主类
    String name;
    String ID;
    int age;

    public void setName(String name){
        this.name=name;
    }

    public void showInfo(){
        System.out.println("name:"+name+"\nage:"+age+"\nID:"+ID);
    }

    public void Maths(){
        System.out.println("学生————学习数学");
    }

}

class uniStudent extends Student{
    String habit;

    @Override
    public void showInfo(){
        super.showInfo();//很奇妙的super关键字
        System.out.println("habit:"+habit);
    }

    @Override
    public void Maths(){
        System.out.println("大学生————学习高等数学");
    }

}

class midStudent extends Student{
    @Override
    public void Maths(){
        System.out.println("中学生————学习初等数学");
    }

}

class Learn{
    public static void exam(Student stu){
        stu.Maths();

    }
}


class Main{
    public static void main(String[] args){
        uniStudent uniStu = new uniStudent();
        uniStu.age=20;
        uniStu.setName("三水点一灯");
        uniStu.habit="金铲铲";
        uniStu.ID="大学生";
        uniStu.showInfo();
        uniStu.Maths();
        Learn.exam(uniStu);//思考该格式

        System.out.println("——————————————————————");

        Student stu = uniStu;//转型
        stu.age=9;
        stu.ID="学生";
        stu.setName("三水气象台");
        stu.showInfo();//转型后还是调用重写的方法
        stu.Maths();
        Learn.exam(stu);

        System.out.println("——————————————————————");

        midStudent midStu = new midStudent();
        midStu.age=16;
        midStu.setName("紫川秀");
        midStu.ID="中学生";
        midStu.showInfo();
        midStu.Maths();
        Learn.exam(midStu);

        System.out.println("——————————————————————");

        Student stu1 = midStu;
        stu1.age=11;
        stu1.ID="另一个学生";
        stu1.setName("荒");
        stu1.showInfo();
        stu1.Maths();
        Learn.exam(stu1);

    }
}

思考:一般方法和静态方法的区别是什么?

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值