百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

你了解多态吗?在哪里用过?

xsobi 2025-01-03 19:36 1 浏览

这是面试过程中常常被问到的,那么今天我们就来从一个完全不懂得的状态到一步步了解什么是多态,来深入掌握多态的概念。

什么是多态?

多态:一个父类和多个子类,即父类引用指向子类对象。在调用一个方法时,从源代码上看,无法确定调用了哪个对象的方法(因为父子类有相同的方法),只有在程序运行期间根据对象变量引用的实际对象才能确定此方法是哪个对象的,这种现象称之为动态绑定。一句话概括就是:事物在运行过程中存在不同的状态。

多态是怎样实现的?

继承:多个子类对同一方法的重写

接口:实现接口并覆盖接口中的同一方法

多态实现的三个必要条件

  • 要有继承关系;
  • 子类要重写父类的方法;
  • 父类引用指向子类对象。

举个例子

首先我们定义几个类,一个父类Person,以及几个子类Student、Teacher、Doctor。

package com.atguigu.polymorphic;

class Person {

public void print() {

System.out.println("父类需改进方法");

}

public void fun() {

System.out.println("父类中其他方法");

}

//行为

public void eat() {

System.out.println("人在吃饭!");

}

public static void look() {

System.out.println("人在看东西!");

}

public void move() {

System.out.println("人在移动!");

}

}

class Student extends Person {

@Override

public void print() {

System.out.println("Student类改进后的方法");

}

public void eat() {

System.out.println("学生在吃面包!");

}

public static void look() {

System.out.println("学生在看书!");

}

public void play() {

System.out.println("学生在进行课外活动!");

}

}

class Teacher extends Person {

@Override

public void print() {

System.out.println("Teacher类改进后的方法");

}

}

class Doctor extends Person {

@Override

public void print() {

System.out.println("Doctor类改进后的方法");

}

}

然后我们创建测试类

package com.atguigu.polymorphic;

public class Test_1008 {

public static void main(String[] args) {

System.out.println("=====重写测试=====");

Person per = new Student();//向上转型,子类对象给了父类的引用

per.print();//由于该方法被覆写,那么调用的是被覆写后的方法

per.fun();//调用父类的fun方法

System.out.println("=====多态测试=====");

Person per1 = new Student();

Person per2 = new Teacher();

Person per3 = new Docter();

per1.print();//由于该方法被覆写,那么调用的是被覆写后的方法

per2.print();

per3.print();

System.out.println("=====行为测试=====");

Person person = new Student();

person.eat();

person.look();

person.move();

}

}

测试结果如下:

=====重写测试=====

Student类改进后的方法

父类中其他方法

=====多态测试=====

Student类改进后的方法

Teacher类改进后的方法

Doctor类改进后的方法

=====行为测试=====

学生在吃面包!

人在看东西!

人在移动!

在以上代码中,Student、Teacher、Doctor类继承了Person类,其中Student子类重写(override)了父类的两个成员方法eat(),look()。其中eat()是非静态的,look()是静态的(static)。并且在测试类Test_1008中 Person person= new Student();语句在堆内存中开辟了子类(Student)的对象,并把栈内存中的父类(Person)的引用指向了这个Student对象。从而满足了Java多态的的必要三个前提。

由测试结果可以看出来

子类Student重写了父类Person的非静态成员方法person.eat();的输出结果为:学生在吃面包!

子类重写了父类(Person)的静态成员方法person.look();的输出结果为:人在看东西!

未被子类(Student)重写的父类(Person)方法person.play()输出结果为:人在移动!

在实际开发工作中,常常遇到一个功能有多种实现方式,比如支付方式,有分微信支付、京东支付、支付宝、银联等支付方式,不同支付方式的大概流程大抵相似,实现细节有所区别。这个时候就可以用到java的多态机制,先定义一个公共接口,接口定义支付流程的各个方法,具体的支付方式实现该接口的方法。在控制层,利用spring的注入获取支付类型和支付方式实现类的引用映射,根据请求需要的支付类型就可以调用对应支付方式的方法,以此实现业务的解耦和拓展。后期需要增加支付方式,只需要实现共同接口即可。

PaymentTypeService.java

/**

* 支付方式接口

*/

public interface PaymentTypeService {

public String type();

public void methodA();

public void methodB();

}

实现A:APaymentTypeServiceImpl.java

/**

* 支付方式A实现类

*/

@Service

public class APaymentTypeServiceImpl implements PaymentTypeService {

private final String type = "A";

@Override

public void methodA() {

// TODO Auto-generated method stub

System.out.println("PaymentType A invoke methodA");

}

@Override

public void methodB() {

// TODO Auto-generated method stub

System.out.println("PaymentType A invoke methodB");

}

@Override

public String type() {

return type;

}

}

实现B:BPaymentTypeServiceImpl.java

/**

* 支付方式B实现类

*/

@Service

public class BPaymentTypeServiceImpl implements PaymentTypeService {

private final String type = "B";

@Override

public void methodA() {

// TODO Auto-generated method stub

System.out.println("PaymentType B invoke methodA");

}

@Override

public void methodB() {

// TODO Auto-generated method stub

System.out.println("PaymentType B invoke methodB");

}

@Override

public String type() {

return type;

}

}

实际引用: DemoController.java

@RestController

public class DemoController {

private Map<String, PaymentTypeService> paymentTypeServices;

/**

* 构造函数初始化不同支付方式类型和实现类引用map

* @param services

*/

public DemoController(@Autowired List<PaymentTypeService> services){

paymentTypeServices = services.stream().collect(Collectors.toMap(PaymentTypeService::type, i->i));

}

/**

* 请求某个支付方式

* @date: 2018年4月23日 下午2:21:28

* @param type

*/

@GetMapping("/test/{type}")

public void test(@PathVariable("type") String type){

// 获取该支付方式实现类

PaymentTypeService service = paymentTypeServices.get(type);

service.methodA();

service.methodB();

}

}

那么我们可以根据以上情况总结出多态成员访问的特点:

  • 成员变量:编译看左边,运行看左边。
  • 构造方法:创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
  • 成员方法:编译看左边,运行看右边。(方法重写的意义)
  • 静态方法:编译看左边,运行看左边。静态和类相关,算不上重写,所以访问还是左边的。只有非静态的成员方法,编译看左边,运行看右边。

多态的优点

可替换性:多态对已存在的代码具有可替换性

可扩充性:增加新的子类并不影响已存在类的多态性、继承性以及其他特性的运行和操作

接口性:多态是父类(超类)通过方法签名,向子类提供了共同的接口,子类可以通过覆写完善或者覆盖这个接口。

灵活性:在应用中体现了灵活多样的操作,提高了使用效率。

多态的使用场景

多态的实现依赖于继承,先声明一个父类的实例,再于合适之时给它分别赋予不同的子类实例,此后操作该实例就仿佛操作子类的实例一般。就好比一个退了伍的军人去当了厨师,他的首先是一个人,当有召时穿上军服就是一名军人,然后在工作是就是一名厨师。这个现象便是多态特性的一个实际运用,所谓多态,意思是有多种状态。

引入多态概念的好处是,只要某些类型都从同一个父类派生而来,就能在方法内部把它们当作同一种类型来处理,而无需区分具体的类型。仍以人的不同职业为例,不管是学生、医生还是教师,都是某种职业,于是完全可以定义一个相似方法,根据输入的不同职业的参数,让这这个职业自己去进行相应的操作。

总结

定义方法参数列表时、定义方法返回值类型时、定义类的成员变量时、定义数组元素类型时,都定义为父类类型,这样就可以传递、返回、赋值、装任意子类类型的对象定义时定义父类类型使用时使用子类类型的对象

相关推荐

听说你还不知道Java代码是怎么运行的?

作者:Jay_huaxiao前言作为一名Java程序员,我们需要知道Java代码是怎么运行的。最近复习了深入理解Java虚拟机这本书,做了一下笔记,希望对大家有帮助,如果有不正确的地方,欢迎提出,感激...

如何开始学习JAVA编程?

#记录我的9月生活#...

java后端开发需要学什么?

Java属于后端开发中最常见的语言之一,Java这种语言的体系比较中立,而且具备了构建多线程的能力,在许多大型互联网平台Java的应用范围特别广泛。  java后端主要涉及到如下4个技术:  第一、S...

细思极恐:你真的会写Java吗?

导语自2013年毕业后,今年已经是我工作的第4个年头了,总在做java相关的工作,终于有时间坐下来,写一篇关于java写法的一篇文章,来探讨一下如果你真的是一个java程序员,那你真的会写java吗?...

七年Java开发的一路辛酸史:分享面试京东、阿里、美团后的心得

前言我觉得有一个能够找一份大厂的offer的想法,这是很正常的,这并不是我们的饭后谈资而是每个技术人的追求。像阿里、腾讯、美团、字节跳动、京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司...

我把Java基础编程及思维导图整理的超级详细,小白都能看懂

Java基础编程及其思维导图目录:Java学习导图一、Java基本语法1.关键字与标识符2.变量分类3.运算符4.流程控制二、数组1.数组概述2.一维数组3.二维数组4.数组常见算法5....

Java 开发中的 9 个实用技巧:案例详解

Java开发中,总有一些技巧能够帮助我们提高代码质量和开发效率。下面,我们来分享9个Java技巧,每个技巧都附上实际案例,帮助你在工作中立刻应用。1.合理使用final关键字...

Java 20年,以后将往哪儿走?

在今年的Java20周年的庆祝大会中,JavaOne2015的中心议题是“Java的20年”。甲骨文公司Java平台软件开发部的副总裁GeorgesSaab的主题演讲就将关注点放在了java...

推荐1个java快速开发项目,让你接私活不用愁

??大家好,我是小编南风吹,每天推荐一个小工具/源码,装满你的收藏夹,让你轻松节省开发效率,实现不加班不熬夜不掉头发!...

教你用Java开发一个简单的JVM

一、前言几年前,接到一个开发任务:用Java开发能运行Java智能合约的虚拟机。在开发Java智能合约时,只能使用智能合约SDK提供的类和一些Java常用类(8种基本数据类型包装类;String、Bi...

java实战教程(一)软件开发流程&amp;开发模式

这里小编为了方便处于不同学习阶段的童鞋,准备了三个系列的文章,java系列教程、java实战教程、java进阶教程,对于刚入坑的童鞋,可以先按照这三个系列教程一步步的了解,循序渐进,java实战系列教...

Java 核心技术之入门指南:全面解析Java概述

大家好,这里是Java码牛!Java核心技术入门:全面解析Java概述一、引言Java,作为一门在当今信息技术领域中被广泛应用于企业级开发的主流编程语言,其核心技术的精准掌握对于众多开发者而言,具有...

小白如何轻松上手Java开发?

Java,这款流行的编程语言,被广大开发者所钟爱。但对于初学者来说,如何入门确实是一个大问题。尤其对于毫无经验的小白,从何处开始、如何推进,都是关键。本文将带你走进Java的世界,为你揭示从零到一的进...

初学Java应该知道的知识点:Java的程序开发是什么?

Java的程序开发是什么呢?下面和千锋广州小编一起来看看吧!一般来说,Java的程序开发包括三个步骤:编写程序,编译程序,运行程序编写程序——Java源代码,.Java文件编译程序——Javac用来进...

厉害了!全靠经典之作-Java编程思想,把小白教的明明白白

今天我们来聊聊这本《Java编程思想》从我学习Java的经验来看,《ThinkinginJava》是讲解Java编程的最佳书籍!  这本书不仅详细地介绍Java语法、知识点、API类库使用,更...