A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 嗬嗬嗬_000 中级黑马   /  2015-7-25 22:13  /  256 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 嗬嗬嗬_000 于 2015-7-25 22:17 编辑

多态
定义:
某一类事物的多种存在形态.
例:
动物中的猫,狗.
对象的多态性
猫和狗都继承于动物
class Animal{}class Cat extends Animal{}
class Dog extends Animal{}
对象cat即具备Cat形态又具备Animal 形态
Cat cat = new Cat();
Animal cat = new Cat();
这个就是对象的多态性(一个对象,两种形态)
多态子啊代码中的体现:
父类或者接口引用指向其子类对象
多态的好处
有一个动物类Animal
  1. abstract class Animal{
  2.     abstract void eat();
  3. }
复制代码


有其他多个类猫,狗继承于动物类
  1. <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-bottom: 16px; padding: 16px; line-height: 1.45; border-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);"><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; border-radius: 3px; word-break: normal; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">class Cat extends Animal{
  2.     void eat(){
  3.         System.out.println("吃鱼")
  4.     }
  5. }
  6. class Dog extends Animal{
  7.     void eat(){
  8.         System.out.println("吃鱼")
  9.     }
  10. }</code></pre>
复制代码

这时,如果给多个猫运行eat的方法,再给狗运行eat方法时:
  1. method(new Cat());
  2. method(new Cat());
  3. method(new Dog());  
  4. void method(Cat c){
  5.     c.eat;
  6. }
  7. void method(Dog g){
  8.     g.eat;
  9. }
复制代码

如果后期再添加其他继承于动物的类,就会发现需要重复写 method方法来实现eat方法.
这时,如使用多态特性,只需要一个方法:
  1. void method(Animal a){
  2.     a.eat;
  3. }
复制代码

就可以轻松实现.
所以,多态的好处显而易见:
提高了代码的扩展性前期定义的代码,可以使用后期的内容.
多态的局限性
要使Cat加一个catchMouse方法时不能实现.
  1. void method(Animal a){
  2.     a.eat;
  3.     a.catchMouse;
  4. }
复制代码

所以多态的局限性是:
不能使用(调用)子类特有的内容
多态的前提:
  • 必须有关系:继承,实现;
  • 要有覆盖;
多态_转型向上转型
自动类型提升,Cat对象提升为Animal类型.这时Cat访问就出现了局限性,无法访问到其的特有功能.
Animal a = new Cat();a.eat;
作用:限制对特有功能的访问.
向下转型
如果还想用具体对象的特有功能,这时可以将对象向下转型
Cat c = (Cat)a;
c.eat();
c.catchMouse();
向下转型的目的:为了使用子类中的特有方法.
注意
对于转型,自始自终都是子类对象再做着类型的变化.
如果创建一个Animal对象,无法将其进行向下转型
//错误
Animal a = new Animal();
Cat c1 = (Cat) a;
创建的对象也只能被转换成对应的子类对象,如转换成其它子类对象,会导致类型转换异常
//错误
Animal a = new Dog();
Cat c = (Cat) a;
多态_类型判断
instanceof
用于判断对象的具体类型,只能用于引用数据类型判断.通常在向下转型前用于健壮性的判断.
加入逻辑判断,增强代码的健壮性
  1. public static void method(Animal a){
  2.     a.eat;
  3.     if(a instanceof Cat){
  4.         Cat c = (Cat)a;
  5.     }
  6.     if(a instanceof Dog){
  7.         //...
  8.     }
  9. }
复制代码


多态_成员特点
多态时,成员的特点
  • 成员变量
  • 成员函数
  • 静态函数
成员变量的特点
  • 编译时:参考引用型变量所属的类中是否有调用的成员变量,有则编译成功.没有就编译失败.
  • 运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量.
简单的来说:编译和运行都参考左边.

  1. class Fu{
  2.     int num = 3;
  3. }
  4. class Zi{
  5.     int num = 4;
  6. }
  7. class DuoTai{
  8.     public static void main(String[] args){
  9.         Fu f = new Zi();
  10.         System.out.println("num="f.num);
  11.     }
  12. }
复制代码

运行结果为:
num=3;
原因:实例化以后,子类已经提升为父类型了,所以找的是父类的num.(覆盖只发生在函数上)
当删除父类中的
num = 3;
语句,编译时报错,因为提升为父类型后,其中没有num变量了.
成员函数(非静态)的特点
  • 编译时:参考引用型所属的类中是否有调用的函数,有则编译成功,没有则编译失败
  • 运行时:参考的是对象所属的类中是否有调用的函数.
简单的来说:编译看左边,运行看右边.

  1. class Fu{
  2.     void show(){
  3.         System.out.println("fu show");
  4.     }
  5. }
  6. class Zi extends Fu{
  7.     void show(){
  8.         System.out.println("fu show");
  9.     }
  10. }
  11. class DuoTai{
  12.     public static void main(String[] args){
  13.         Fu f = new Zi();
  14.         f.show();
  15.     }
  16. }
复制代码

运行结果:
zi show
去除父类中的方法后,会编译失败.
静态函数的特点
  • 编译时:参考引用型变量所属的类中是否有调用的静态方法,有则编译成功.没有就编译失败.
  • 运行时:参考引用型变量所属的类中是否有调用的静态方法,并运行该所属类中的成员变量.
简单的来说:编译和运行都参考左边.
  1. <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; margin-bottom: 16px; padding: 16px; line-height: 1.45; border-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);"><code class="java" style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; border-radius: 3px; word-break: normal; border: 0px; display: inline; max-width: initial; overflow: initial; line-height: inherit; word-wrap: normal; background: transparent;">class Fu{
  2.     static void method(){
  3.         System.out.println("fu static run");
  4.     }
  5. }
  6. class Zi extends Fu{
  7.     static void method(){
  8.         System.out.println("zi static run");
  9.     }
  10. }
  11. class DuoTai{
  12.     public static void main(String[] args){
  13.         Fu f = new Zi();
  14.         f.method();
  15.     }
  16. }</code></pre>
复制代码

运行结果:
fu static run
非静态依赖的是对象,必须动态绑定在指定的对象上,但静态方法不需要.不依赖于对象,依赖于类型.



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马