java基础篇(三) ----- java面向对象的三大特性之多态

封装(encapsulation)
类使得数据和对数据的操作捆绑在一起,从而对使用该类的其他人来说,可以不管它的实现方法,而只管用它的功能,从而实现所谓的信息隐藏;
 
继承(inheritance)
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。比如可以先定义一个类叫animal,animal具有以下属性:   眼睛,鼻子,耳朵 而又由animal这个类派生出dog和cat两个类,为dog添加一个看家的功能,而为cat添加一个抓鱼的功能。
如果两个类存在is-a关系就可以使用继承,同时继承也为实现多态做了铺垫。那么究竟什么是多态?多态的实现机制是怎么样的? 
 
 
其实所谓的多态是一个程序中同名方法但功能不同,允许不同类的对象对同一消息作出响应,它是面向对象中最重要的感念之一
 
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。
 
通俗的解释多态就是,假如有个方法名叫:“动物的叫声” 那么,当你传递的参数是动物狗,则调用狗叫声,是猫,则调用猫叫声,这就是多态。
 
以下介绍两个很形象的例子
 
比方一下:

你和你朋友都是烟鬼,

某日,你没有带烟, 而你朋友有n种烟,

你说: 来根烟,

朋友给你一根;

你通过烟的过滤嘴, 品出为白沙烟

你再要一根,

品出这次是芙蓉王,

再要一根,

品出这次是熊猫

...

上面描述的就是多态!

烟 a = 白沙
烟 b = 芙蓉王
烟 c = 熊猫
.............
    这里所表现的的就是多态。白沙、芙蓉王、熊猫都是烟的子类,我们只是通过烟这一个父类就能够引用不同的子类,这就是多态——我们只有在运行的时候才会知道引用变量所指向的具体实例对象。 
 
Yan a = new BaiSha();
这里我们这么理解,我们定义了一个Yan类型的a,由于BaiSha是继承Yan的,所以BaiSha可以自动向上转型为Yan,所以a是可以指向BaiSha的实例的,这样做有个强大的好处,就是我们知道子类是父类的扩展,拥有比父类更加强大的功能,如果我们敌营一个指向子类的父类的引用。不但可以使用子类的共性,还可以使用子类的强大功能。但是世间万物没有完美的,向上转型存在一丝缺憾,他会导致一些属性和方法丢失。导致我们不能获取他们,所以我们定义父类类型的引用可以调用父类中已经定义的属性和方法,对于那些只在子类中存在的属性和方法就望尘莫及了、、、
 

再举一个鸡的例子:
鸡是所有其它鸡的基类, 定义了一个方法shape(), 此方法能指明鸡的形态. 所有的子类[火鸡,山鸡,田鸡等],都有这个shape方法, 表明自己的形态,

如果用下面的方法定义我需要具体的鸡,

[基类 引用 = 实现类的对象]


for example:

鸡 a = new 火鸡();

鸡 a = new 田鸡();

鸡 a = new 山鸡();

鸡 a = new 母鸡();



当我使用的时候, 我采用 a 这个引用,

a.shape(), 就会得到鸡的形态.


如果我定义的是

鸡 a = new 火鸡();

那么a.shape得到的是火鸡的形态, 而不需要用具体的

火鸡 a = new 火鸡(); 再通过a.shape得到火鸡的形态

----------------------------------------------------------------------------------
 
java多态的一个经典实例:
 
class A ...{
         public String show(D obj)...{
                return ("A and D");
         } 
         public String show(A obj)...{
                return ("A and A");
         } 

class B extends A...{
         public String show(B obj)...{
                return ("B and B");
         }
         public String show(A obj)...{
                return ("B and A");
         } 
}
class C extends B...{} 
class D extends B...{} 

(二)问题:以下输出结果是什么?

        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C(); 
        D d = new D(); 
        System.out.println(a1.show(b));   ①
        System.out.println(a1.show(c));   ②
        System.out.println(a1.show(d));   ③
        System.out.println(a2.show(b));   ④
        System.out.println(a2.show(c));   ⑤
        System.out.println(a2.show(d));   ⑥
        System.out.println(b.show(b));     ⑦
        System.out.println(b.show(c));     ⑧
        System.out.println(b.show(d));     ⑨    

(三)答案

              ①   A and A
              ②   A and A
              ③   A and D
              ④   B and A
              ⑤   B and A
              ⑥   A and D
              ⑦   B and B
              ⑧   B and B
              ⑨   A and D

 ①②③比较好理解,一般不会出错。④⑤就有点糊涂了,为什么输出的不是"B and B”呢?

首先我们要知道,当超类对象引用变量引用了子类对象时,是被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。这句话对多态进行了一个概括

其实在继承链中对象方法的调用存在一个优先级: this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

遵循上述对象方法调用的优先及我们不难发现此处的原因!

对象多态性主要分两种类型:

  (1)向上转型,子类对象向父类对象转型时,java系统会自动完成。

  (2)向下转型, 父类对象向子类对象转型时,必须要明确指明要转型的子类类型。

java实现多态需要:(1)继承(或给予接口实现) (2)重写 (3)父类的引用指向子类的对象!!

本人学习总结所用,如有纰漏错误之处请指正,定虚心学习改正!谢谢。

不为失败找借口,只为成功找方法!!!!

 
原文地址:https://www.cnblogs.com/fanhongyun/p/4419403.html