前言:
今天我准备探讨一下多态的终极奥义,Java也学习了两年了,但是对于多态一直不是很理解,上周刚刚来到青软实训基地,才有了时间深入学习这些熟知用法而不知底层的知识。 花了一天时间来了解多态存在的意义。本篇博客让我们从一个完全不懂得状态一步步了解什么是多态,深入掌握多态的概念。
什么是多态?
让我们看看百度是怎么定义多态的,话不多说,上图!
望文生义,第一眼看到多态,感觉就是多种形态的意思,作为Java三大特性之一,多态究竟是什么呢?
百度已经解释的很清楚了,实际上就是字面意思,拥有多种形态的意思,多态是允许将父类对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
读到这里好像明白了点,就是让父类拥有更多的属性呗!那看看代码看看是不是这个意思。
比如父接口是超级英雄(SuperHero)
public interface SuperHero {
int age = 0;
String sex = "";
//超级英雄的移动方式
public void move() ;
//超级英雄的攻击方式
public void Hit();
}
子类A是美国队长(CaptainAmerica)
public class CaptainAmerica implements SuperHero{
int age = 89;
String sex = "男";
@Override
public void move(){
System.out.println("俺是美队,俺跑的移动");
}
@Override
public void Hit() {
System.out.println("俺是美队,一锅盖悠死灭霸!");
}
}
子类B是钢铁侠(IronMan)
public class IronMan implements SuperHero{
int age = 49;
String sex = "男";
@Override
public void move() {
System.out.println("没想到吧,我会飞,hiahiahia!~");
}
@Override
public void Hit() {
System.out.println("我是铁男,兄弟,全是高科技,neng死灭霸!");
}
}
然后在main方法中按照多态的定义生成对象:
public static void main(String[] args) {
SuperHero superHero = new CaptainAmerica();
superHero.move();
superHero.Hit();
System.out.println(((CaptainAmerica) superHero).sex);
System.out.println(((CaptainAmerica) superHero).age);
System.out.println("--------我是华丽的分割线---------");
superHero = new IronMan();
superHero.move();
superHero.Hit();
System.out.println(((IronMan) superHero).sex);
System.out.println(((IronMan) superHero).age);
}
打印结果:
俺是美队,俺跑的移动
俺是美队,一锅盖悠死灭霸!
男
89
--------我是华丽的分割线---------
没想到吧,我会飞,hiahiahia!~
我是铁男,兄弟,全是高科技,neng死灭霸!
男
49
嗯,原来这就是多态,so easy,可是短暂的兴奋过后,我突然意识到了一个问题,如果从技术角度去实现的话,我直接用子类去引用子类的对象完全OK啊,无论是从效率还是结果,都完全一样,那么多态有个P用?
具体实现如下:
public static void main(String[] args) {
CaptainAmerica captainAmerica = new CaptainAmerica();
captainAmerica.move();
captainAmerica.Hit();
System.out.println(captainAmerica.sex);
System.out.println(captainAmerica.age);
System.out.println("--------我是华丽的分割线---------");
IronMan ironMan = new IronMan();
ironMan.move();
ironMan.Hit();
System.out.println(ironMan.sex);
System.out.println(ironMan.age);
}
结果如下:
俺是美队,俺跑的移动
俺是美队,一锅盖悠死灭霸!
男
89
--------我是华丽的分割线---------
没想到吧,我会飞,hiahiahia!~
我是铁男,兄弟,全是高科技,neng死灭霸!
男
49
结果完全相同,而且从代码量上看,后者反而更少一些,那么多态的存在岂不是太显鸡肋?
后来经过网上的查找,终于找到了多态的终极奥义:
多态性:发送消息给某个对象,让该对象自行决定响应何种行为。
通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。
java 的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
说白了,假设你站在开发者的角度去思考而不是一个苦b的程序猿角度,我要你设计一个漫威英雄生产器,但是用户有不同的需求,有的喜欢钢铁侠,有的喜欢美队,有的都喜欢。所以你应该设计一个接口,里面包含超级英雄的通性,再写出不同的实现类,用户有不同需要的时候,直接从你这个漫威英雄生产器中去找到自己喜欢的英雄,这样会很省事,如果没有这个漫威英雄生产器,你每个超级英雄所有的属性和方法必须自己再一个一个写,虽然也可以,但是很不方便。有了这个通用的接口,什么样的英雄都可以通过给不同的实例化对象让其去引用对象去实现。不知道大家有没有玩儿过红外线灯,通过替换前面不同的灯头,可以射出不同的图案,道理差不多,不安灯头也可以亮,但是没有图案,想要不同的图案只需安装对应的灯头即可,很方便。但是如果没有灯头,你就需要生产拥有不同图案的红外线灯,虽然也能达到射出不同图案的效果,但是要花更多的钱而且麻烦。漫威英雄生产器就相当于这个红外线灯,通过new不同的漫威英雄,以达到射出不同图案的效果,new IronMan();那么就是射出钢铁侠的图案,new CaptainAmerica();就可以射出美队的图案,但是他们都是在漫威英雄这个灯上面,归根到底还是一个红外线灯,但是你每次需要新的漫威英雄,就赋值给对应的类,例如:IronMan ironman = new IronMan(); CaptainAmerica captainAmerica = new CaptainAmerica(); 就相当于又生产了两个红外线灯,试想如果需要更多的超级英雄呢?每个都需要重新生产红外线灯?那不是很麻烦么?