多态详解
1、如何理解多态性?
理解为一个事物的多种形态。比如一万个人的眼中有一万个哈姆雷特。
再比如,你女朋友跟你说她想养一个宠物,但是她并没有说是什么宠物,那狗、猫、兔子这些都属于宠物这个范畴,属于动物这个大类。那你给她给她搞一只狗是不是宠物?当然是!只不过她想养猫啊。
2、在java中的体现
父类的引用指向子类的对象。或子类的对象赋给父类引用。
先准备三个类:分别是People,Man,Woman,并且Man和Women都继承People类
People类:
Man类:
Woman类:
再创建一个Test测试类来验证多态:
这段代码就是多态性,比如你要出差,公司安排一个人,这个人可以是男人、可以是女人,代码中People就代表了人这个代码,Man代表他是个男人。数学就是People包含Man。java中就是声明的是父类类型,但是实际上new的是一个子类的实际对象。
3、多态性的应用
运行结果:
代码声明的是People的类型,但是运行结果是Man的代码。这里People(父类)相当于一个大类、Man(子类)属于这个大类。
运行结果也说明了,声明的是一个People类(父类)的方法,实际执行的是Man(子类)重写People类(父类)的方法。(如果父类的方法没有被子类重写那么运行的是父类的方法)。
总结一下就是;
1)成员变量:编译看父类、运行看父类。
2)非静态成员方法:编译看父类、运行看子类。
3)静态方法:编译看父类、运行看父类。
多态使用方法,不适用于属性(变量)。
4、多态性使用的前提:
1)要有继承关系。
2)要有方法被重写。
5、多态的好处:
准备代码:
Animal类:
Dog类:
Cat类:
AnimaTest类:
注意:在afopt里面使用animal调用方法的时候,只能调用Animal这个类里面声明的方法。
举例:
举例:
总结:
1)极大的减少了代码的冗余,不需要定义多个重载的方法
2)使用父类类型作为方法的形参、可以接受该父类类型的任意子类对象。
3)使用父类类型作为方法的返回值类型,在方法中可以返回该父类类型的任意子类对象。
6、多态的弊端:
抛出一个问题:
1、针对于创建的对象,在内存中是否加载了Man类中声明的特有的属性和方法?(加载了!)
2、那能不能直接调用Many中加载的特有的属性和方法? (不能)
对比一下这两断代码的区别:
答:第一段代码不仅可以调用子类的方法,同时也可以调用父类的方法
第二代码只能运行父类的方法。
那这样为什么不直接都创建成第一段代码那样呢?
总结:
1)所以多态多用于形参的时候。
2)在多态的场景下,我们创建了子类的对象,也加载了子类的属性和方法。但是因为声明的是父类的类型,导致我们没有办法直接调用子类特有的属性和方法。
7、处理多态弊端的方法
1、向下转型:
向下转型的使用方法跟基本数据类型强制转换的用法一样。
代码:
运行结果:
转型对比:
很明显,转型后,已经可以调用子类特有的属性和方法了。
注意:
这样会编译错误
因为我声明是Person父类指向一个Woman类的子类。
8、关键字:instanceOf (判断类型)
建议在向下转型之前,使用instanceof判断,避免出现类型转换异常。
格式:a instanceOf B, 判断对象a的类型是否是类型B,返回的结果是一个boolean类型。
代码:
表示判断p1是否是Man类型,如果p1是Man,返回ture,然后p1转换成Man类型,这样就可以调用Man里面的特有的属性和方法了。
就相当于把 People m1 =new Many()=>Man m2=new Man()。
这样可以避免强制转换错误。
最后最后可以举个例子什么时候使用多态:
假如晚上你在你家附近看到一只动物,但是你不确定你看的是牛呢?还是马呢?还是牛马呢?所以你跟你妈妈说你晚上在家附近看见了一头牛马!