Java 多态

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性是对象多种表现形式的体现。

比如我们说"宠物"这个对象,它就有很多不同的表达或实现,比如有小猫、小狗、蜥蜴等等。那么我到宠物店说"请给我一只宠物",服务员给我小猫、小狗或者蜥蜴都可以,我们就说"宠物"这个对象就具备多态性

在Java中,所有的对象都具有多态性,因为任何对象都能通过IS-A测试的类型和Object类。

多态存在的三个必要条件
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。

 多态的好处

1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

多态的概念

  不要把函数重载理解为多态。

  因为多态是一种运行期的行为,不是编译期的行为。

  多态:父类型的引用可以指向子类型的对象。

  比如 Parent p = new Child();

    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;

    如果有,再去调用子类的该同名方法。

    (注意此处,静态static方法属于特殊情况,静态方法只能继承,不能重写Override,如果子类中定义了同名同形式的静态方法,它对父类方法只起到隐藏的作用。调用的时候用谁的引用,则调用谁的版本。)

  如果想要调用子类中有而父类中没有的方法,需要进行强制类型转换,如上面的例子中,将p转换为子类Child类型的引用。

  因为当用父类的引用指向子类的对象,用父类引用调用方法时,找不到父类中不存在的方法。这时候需要进行向下的类型转换,将父类引用转换为子类引用。   

class Animal{
    public void sing() {
        System.out.println("Animal is singing!");
    }
}

class Dog extends Animal{
    public void sing(){
        System.out.println("Dog is singing!");
    }
}

class Cat extends Animal{
    public void sing(){
        System.out.println("Cat is singing!");
    }
    public void eat(){
        System.out.println("Cat is eating!");
    }
}
 1 多态示例代码
 2 
 3 public class PolyTest{
 4 
 5     public static void main(String[] args){
 6         
 7         //向上类型转换
 8         Cat cat = new Cat();
 9         Animal animal = cat;
10         animal.sing();
11 
12                 
13         //向下类型转换
14         Animal a = new Cat();
15         Cat c = (Cat)a;
16         c.sing();
17         c.eat();
18 
19 
20         //编译错误
21         //用父类引用调用父类不存在的方法
22         //Animal a1 = new Cat();
23         //a1.eat();
24         
25         //编译错误
26         //向下类型转换时只能转向指向的对象类型        
27         //Animal a2 = new Cat();
28         //Cat c2 = (Dog)a2;
29 
30     }
31 }

例子的执行结果:

两种类型的类型转换

  (1)向上类型转换(Upcast):将子类型转换为父类型。

  对于向上的类型转换,不需要显示指定,即不需要加上前面的小括号和父类类型名。

  

  (2)向下类型转换(Downcast):将父类型转换为子类型。

  对于向下的类型转换,必须要显式指定,即必须要使用强制类型转换。

  

  并且父类型的引用必须指向子类的对象,即指向谁才能转换成谁。

  不然也会编译出错:

  因为父类引用指向的是Cat类的对象,而要强制转换成Dog类,这是不可能的。

  多态学习的第二部分,抽象类和接口:http://www.cnblogs.com/mengdd/archive/2012/12/25/2832656.html

  

转自:http://www.cnblogs.com/mengdd/archive/2012/12/25/2832288.html

原文地址:https://www.cnblogs.com/jkguo/p/5083285.html