Java——多态

ops/2024/10/19 9:34:29/

1.多态简介

        多态,字面意思来看就是多种形态,即当去执行某个行为,会因为对象的不同而产生不同的效果。在java语言当中就是根据对象的性质不同,对同一个方法进行调用时,得到了不同的执行结果。

        在理解多态中必须时刻牢记三个条件:

(1)存在继承关系,并且发生向上转型。

(2)子类对父类的方法进行重写。

(3)通过父类对象的引用去调用这个重写的方法。

        在满足了如上三个条件后,就会发生动态绑定,而动态绑定则是多态的基础。

         接下来,我们将会对刚才涉及到的概念进行一一解释。

2.向上转型和向下转型

        我们知道,在继承关系中存在父类和子类,父类对象和子类对象之间可以存在类型转换。当我们将子类对象赋值给父类对象,这就构成了向上转型;当我们将父类对象赋值给子类对象,这就构成了向下转型。

        需要指出的是,当对象进行向上转型后,就不可以再调用子类特有的方法了。如果想要调用子类方法,那么就需要进行向下转型还原为子类对象。

2.1 向上转型

        向上转型:将子类对象赋值给父类对象

        向上转型常见发生情况:

直接赋值

java">class Base{}class Derived extends Base{}public class Test {public static void main(String[] args) {Base b1 = new Derived();    //直接赋值}
}

作为方法的参数,将子类对象实参传给父类对象形参

java">class Base{}class Derived extends Base{}public class Test {public static void func(Base b){}public static void main(String[] args) {Derived d = new Derived();func(d);    //传参}
}

作为返回值,将子类对象以父类对象的形式返回

java">class Base{}class Derived extends Base{}public class Test {public static Base func(){Derived d = new Derived();return d;}public static void main(String[] args) {func(); //返回值}
}

2.2 向下转型

        向下转型:将父类对象赋值给子类对象

        向下转型具体来说就是将一个子类对象向上转型后的父类对象还原为其原来的子类对象。由于向下转型存在着安全性问题,所以向下转型的时候需要强制类型转换。

java">class Base{}class Derived extends Base{}public class Test {public static void main(String[] args) {Derived d = (Derived) new Base();}
}

        不完全主要是因为父类可以被很多类继承,所以父类拥有众多子类,无法肯定将要向下转型的对象是不是就是指定的子类,所以存在安全性问题。这时候就需要使用instanceof关键字对对象进行检查,如果是指定子类向上转型的对象,则表达式为真。

java">class Base{}
class Derived1 extends Base{public void func(){System.out.println("Derived1");}
}
class Derived2 extends Base{public void func(){System.out.println("Derived2");}
}
public class Test {public static void main(String[] args) {Base b1 = new Derived1();if(b1 instanceof Derived2){Derived2 d = (Derived2)b1;d.func();}if(b1 instanceof Derived1){Derived1 d = (Derived1)b1;d.func();}}
}

Derived1

3. 重写

3.1 重写的实现

        重写就是子类对父类的方法进行重新编写,所以要求重写的方法除了方法体以外,函数名、返回值、参数等都不可以改变。

java">class Base{public void func(){System.out.println("Base::func()");}
}class Derived extends Base{@Overridepublic void func(){System.out.println("Derived::func()");}
}

        在实现重写的过程中存在如下需要注意的关键点:

①重写是父类和子类方法之间的关系,所以重写必然依附于继承关系

②子类中重写的方法和父类的方法相比,返回值、方法名、参数列表必须完全一致

③被重写的方法的访问修饰限定符,子类必须大于等于父类的

private修饰的方法不可以重写,因为在子类中都无法访问到这个方法。

static修饰的方法不可以重写

final修饰的方法不可以重写,这也正是final修饰方法的作用。

构造方法不可以被重写

⑧代码中存在一行:@Override 。这是一个注解,他是用于提示我们也是在告诉编译器接下来写的方法是一个重写方法,所以编译器就会进行检查,当发现不是重写方法的时候就会报错。

3.2 重写的使用

        那么重写有什么作用呢?我们可以通过代码进行测试:

java">class Base{public void func(){System.out.println("Base::func()");}
}class Derived extends Base{public void func(){System.out.println("Derived::func()");}
}public class Test {public static void main(String[] args) {Base b = new Derived();b.func();}
}

Derived::func()

        可以发现当我们使用向上转型后的对象调用重写方法的时候,对象调用了子类的方法。这个向上转型对象调用子类重写方法的过程,由于在编译时不确定方法的行为,所以需要等到程序运行时才能确定,因此称为动态绑定。同样的,一般的函数(包括函数重载),都是可以在编译时根据所传递的信息(如函数名、参数)等,就可以确定所调用的方法,因而称谓静态绑定。

        在有了如上基础后,我们就可以再来理解一下之前的toString。首先需要明确的一点,所有类的父类都默认是Object(一个java中提供的类),而Object中有toString方法。当我们的类(子类)不实现toString的时候,就会默认调用父类的toString方法;当我们自己写了toString方法后就构成了重写,所以这个时候再调用toString,根据继承关系子类优先原则,就会先调用子类的方法。所以会发现,toString方法的访问限定符只可以是public,这就是重写在发挥作用。

4.总结

        在父类的构造方法中是可以调用子类的重写方法的,但是由于子类初始化在父类之后,所以会产生问题,不建议这样使用。

        通过以上的介绍,可以为多态下一个定义了,多态就是对不同对象尽管看似调用了同一种方法,但是由于对象是向上转型的,方法是存在重写的,所以相当于父类对象调用了不同的子类的重写的方法,因此形成了多态。


http://www.ppmy.cn/ops/4116.html

相关文章

Jmeter03:直连数据库

1 Jmete组件:直连数据库 1.1 是什么? 让Jmeter直接和数据库交互 1.2 为什么? 之前是通过接口操作数据库,可能出现的问题:比如查询可能有漏查误查的情况,解决方案是人工对不,效率低且有安全隐患…

探索数据结构:BF与KMP的灵活应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:数据结构与算法 贝蒂的主页:Betty’s blog 1. 什么是字符串匹配算法 字符串匹配是计算机科学中的一个基础概念&…

Go Web框架-Beego

本文主要分享GO语言常用的web框架:Beego框架,简单分享如何快速入门Beego Beego框架 Beego框架的简介 Beego框架是一款开源的由国人开发的全栈式的Web框架,它采用了MVC架构,支持自动化路由、ORM、Session、日志、缓存等功能&#x…

数据结构:查找与排序

注&#xff1a;以下代码均为C 查找 一、线性表的查找 1. 顺序查找 int search_seq(vector<int> s, int key){for(int i 0; i < s.size(); i){if(s[i] key)return i;}return -1; }2. 折半查找 (1)非递归&#xff1a;循环 int search_bin1(vector<int> s,…

FreeSWITCH 1.10.10 简单图形化界面17 - ubuntu22.04或者debian12 安装FreeSWITCH

FreeSWITCH 1.10.10 简单图形化界面17 - ubuntu22.04或者debian12 安装FreeSWITCH 界面预览00、先看使用手册0、安装操作系统1、下载脚本2、开始安装3、登录网页FreeSWITCH界面安装参考:https://blog.csdn.net/jia198810/article/details/132479324 界面预览 http://myfs.f3…

设计模式-组合模式

目录 &#x1f9c2;1.组合设计模式 &#x1f953;2.优缺点 &#x1f32d;3.核心角色 &#x1f37f;4.代码实现 1.组合设计模式 1.又叫部分整体模式&#xff0c;是用于把一组相似的对象当作一个单一的对象2.组合模式使得用户可以使用一致的方法操作单个对象和组合对象3.部分…

Rich,最强大的可视化界面和文本输出python库

Rich,可美化界面和文本输出最强python库 什么是Rich 库&#xff1f; Rich是一个用于在 Python 中创建美观、颜色丰富的命令行界面和文本输出的库. Rich有那些功能&#xff1a; Rich库可以帮助开发者创建漂亮的终端输出,包含丰富的格式化选项,如颜色、样式、表格、进度条等. …

Java数据结构-二叉树

目录 1. 树与二叉树1.1 树1.2 二叉树1.3 树的相关概念1.4 特殊的二叉树1.5 二叉树性质1.6 二叉树的存储与表示方法 2. 二叉树遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历2.4 层序遍历 3. 二叉树基本操作3.1 求树的所有结点个数3.2 求叶子结点个数3.3 求第k层结点个数3.4 求二叉树…