我的Java Web之路 - Java基础(7)- 多态

介绍

是时候聊聊多态了。

什么是多态

多态对应的英文单词是polymorphism,百度翻译给出的翻译是:

n. 多型现象,多态性; 多机组合形式;

按字面意思就是多种状态、形态、姿态等等,潜台词就是某个东西具有多种状态、形态、姿态等等。那是什么东西呢?在面向对象的编程语言里面(当然就包括Java了)就是某个方法或函数。

那方法的多种状态、形态、姿态有是个什么意思呢?这其实是指同一个方法具有多个方法体,就是方法的实现。而方法的相同与否是由方法签名决定的。

所以,多态其实本质上是指同一个类同一个方法却具有不同的行为特征。状态、形态、姿态指的就是行为特征。

多态在Java中的技术基础

然而,在Java中,同一个类里面是不可能存在两个签名相同而实现不同的方法的,否则的话会导致无法判断该执行哪个方法,因此在编译时就会报错。

所以,肯定是在两个类中才有可能存在两个签名相同而实现不同的方法,一个实现在这个类,另一个实现在另一个类。如果这两个类毫无瓜葛,那么肯定就与多态的本质(同一个类同一个方法却具有不同的行为特征)自相矛盾了。

所以,这两个类肯定是有某种联系的。我们再想想,什么概念是能够让两个不同的类却又能称为同一个类的?答案就是类的继承/扩展,就是现实中的“某东西是某类东西”的概念,就是“具体和抽象”的思想。比如,男人是人,女人也是人,男人类和女人类就借助于人类建立了某种联系,而人类具有的某个行为在男人类和女人类中是有着不同体现的,比如人类的吃饭这个行为,男人类的体现是狼吞虎咽,女人类的体现是细嚼慢咽。例子不是很恰当,但意思就是这么个意思。

所以说,Java里面多态的技术基础就是方法的覆盖,当然,在Java中覆盖不仅仅发生在类的继承/扩展上,还可能发生在接口的实现上。只有覆盖才能满足两个方法签名相同而实现不同,却又能统一在同一个类同一个方法之中。

示例

人类:

package com.example;

public class Person {

	public void eat() {
		System.out.println("我在吃饭!");
	}
}

男人类:

package com.example;

public class Man extends Person {

	public void eat() {
		super.eat();//人类都要吃饭
		System.out.println("我狼吞虎咽地吃!");
	}
}

女人类:

package com.example;

public class Woman extends Person {

	public void eat() {
		super.eat();//人类都要吃饭
		System.out.println("我细嚼慢咽地吃!");
	}
}

使用人类的外部模块:

package com.example;

/**
 * 
 * 外部模块,使用Person类
 * 可以用Man类和Woman类的对象来配置此模块
 *
 */
public class OuterModule {

	public static void main(String[] args) {

		Person p = new Man();//相当于配置
		p.eat();
		
		p = new Woman();//相当于配置
		p.eat();
	}

}

执行结果可以看出,对同一个类的同一个方法的调用,执行结果却不一样,这就是多态!其根本原因还是在于调用该方法的引用类型变量指向的是一个子类接口实现类的对象。所以,我们只要为这个变量配置不同的子类接口实现类的对象即可获得不同的执行结果。

这好像有点类似于C语言的函数指针,本质上不过是把一段代码包装成数据,然后就可以将它赋值某种特殊类型的变量(实际上代表的是数据存放的地址而已),比如函数指针或引用类型变量,然后就可以用该变量来找到该段代码,从而执行该段代码。

多态的好处

其实,这个需要不断的实践、思考和总结,自己对多态好处的体会才会深刻。

多态的好处最根本上还是围绕代码的可复用性可扩展性这两点上面,似乎封装和继承也是为了这两个目标,不过侧重点不太一样罢了。

首先,从使用多态类/接口的外部模块的角度看,它看到的是一个通用的封装好的可以复用的行为规范(比如示例中的eat行为,HttpServlet中的doGet等行为),而不必为了每一个子类或实现类的具体行为特征去开发一套相同的代码。说白了还是从各种具体行为特征中抽象出共同的行为规范,还是发现重复、消除重复的体现。

然后,从多态类/接口的角度看,我可以自由的实现拥有各种不同具体行为的子类/实现类,有的可能性能更好,有的可能业务功能不一样(就比如你可以实现各种功能的Servlet一样),最后只要把它们配置到外部模块(比如Tomcat中)就可以使用了,这个过程中完全不用修改其他子类/实现类以及外部模块的代码。这就是高可扩展性,就是松耦合。可以参考前面的文章看看Servlet技术中是如何使用多态的。

所谓面向接口编程,也就是为了充分使用多态。在方法的参数和返回值的类型选择上,尽量选择抽象级别更高的接口上,当然,抽象类或普通的父类也可以。

而其他的什么七大面向对象设计原则都多少与多态有关系,当然也与封装、继承有关系,毕竟这三个是面向对象思想的基本特征。

总结

  • 多态本质上是指同一个类同一个方法却具有不同的行为特征
  • 多态在Java中主要通过方法覆盖技术来实现;
  • 方法覆盖可以出现在子类继承父类的情况下,也可以出现在实现类实现接口的情况下;
  • 封装隐藏了实现细节,实现代码模块化(就是类);继承可以扩展已存在的模块(就是类);多态则解耦了外部模块和多态类/接口及其子类/实现类,让它们之间形成只是一种配置关系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值