面向对象三大特性一一多态(polymorphism)

 1 package com.bjsxt.oop.polymorphism;
 2 
 3 public class Animal {
 4     public void voice(){
 5         System.out.println("动物叫声");
 6     }
 7 }
 8 class Cat extends Animal{
 9     public void voice(){
10         System.out.println("喵喵喵");
11     }
12 }
13 class Dog extends Animal{
14     public void voice(){
15         System.out.println("汪汪汪");
16     }
17 }
18 class Pig extends Animal{
19     public void voice(){
20         System.out.println("吭哧吭哧");
21     }
22 }
 1 package com.bjsxt.oop.polymorphism;
 2 
 3 /**引用变量的2中类型
 4  * 1,编译时类由声明事类型决定
 5  * 2,运行时类型 由实际传入的对象类型决定
 6  * 
 7  * 
 8  * 三个必要条件
 9  * 要有继承
10  * 要有重写
11  * 父类引用指向子类对象
12  * @author Administrator
13  *
14  */
15 public class Test {
16     /*如果没有多态,我们需要把每个子类的叫的方法写一遍,重载动物叫声方法 显然不方便
17     public static void testAnimalVoice(Cat c){
18         c.voice();
19     public static void testAnimalVoice(Dog d){
20         d.voice();
21     public static void testAnimalVoice(Pig p){
22         p.voice();
23     }*/
24     //使用多态就很简单  编译时类由声明事类型决定
25     public static void testAnimalVoice(Animal a){
26         a.voice();
27     }
28     public static void main(String[] args) {
29          //运行时类型 由实际传入的对象类型决定
30         /*父类引用指向子类对象
31         Cat c = new Cat();
32         Animal a = c;
33         我们写成下面这样
34         */
35         Animal c = new Cat();
36         Animal d = new Dog();
37         Animal p = new Pig();
38         testAnimalVoice(c);
39         testAnimalVoice(d);
40         testAnimalVoice(p);
41         
42     }
43 }

 我们试着重写方法

我们每一个动物,重写一个属于自己的方法;

 1 package com.bjsxt.oop.polymorphism;
 2 
 3 public class Animal {
 4     public void voice(){
 5         System.out.println("动物叫声");
 6     }
 7 }
 8 class Cat extends Animal{
 9     public void voice(){
10         System.out.println("喵喵喵");
11     }
12     public void catchMouse(){
13         System.out.println("猫抓老鼠");
14     }
15 }
16 class Dog extends Animal{
17     public void voice(){
18         System.out.println("汪汪汪");
19     }
20     public void seeDoor(){
21         System.out.println("狗看门");
22     }
23 }
24 class Pig extends Animal{
25     public void voice(){
26         System.out.println("吭哧吭哧");
27     }
28     public void sleep(){
29         System.out.println("猪在睡觉");
30     }
31 }
32 class Tiger extends Animal{
33     public void voice(){
34         System.out.println("吼吼吼");
35     }
36     public void eat(){
37         System.out.println("老虎在吃饭");
38     }
39 }

我们试着 调用一下

package com.bjsxt.oop.polymorphism;

/**引用变量的2中类型
 * 1,编译时类由声明事类型决定
 * 2,运行时类型 由实际传入的对象类型决定
 * 
 * 
 * 三个必要条件
 * 要有继承
 * 要有重写
 * 父类引用指向子类对象
 * @author Administrator
 *
 */
public class Test {
    /*如果没有多态,我们需要把每个子类的叫的方法写一遍,重载动物叫声方法 显然不方便
    public static void testAnimalVoice(Cat c){
        c.voice();
    public static void testAnimalVoice(Dog d){
        d.voice();
    public static void testAnimalVoice(Pig p){
        p.voice();
    }*/
    //使用多态就很简单  编译时类由声明事类型决定
    public static void testAnimalVoice(Animal a){
        a.voice();
    }
    public static void main(String[] args) {
         //运行时类型 由实际传入的对象类型决定
        /*父类引用指向子类对象
        Cat c = new Cat();
        Animal a = c;
        我们写成下面这样
        */
        Animal c = new Cat();
        Animal d = new Dog();
        Animal p = new Pig();
        Animal t = new Tiger();
        testAnimalVoice(c);
        testAnimalVoice(d);
        testAnimalVoice(p);
        testAnimalVoice(t);
        
        //我们在我们重写了很多类的方法 我们试着调一下
        //c.cathMouse(); 报错The method cathMouse() is undefined for the type Animal
        //咦?说我们的抓老鼠的方法在Animal类里没定义  我让猫抓老鼠和你Animal有什么关系? 原来编译器不通过(编译器没那么智能,你传什么对象他就是啥了你得声明)是因为
        //编译器 只认证不认人 比如 你掉方法  c.cathMouse(); c是什么呢?  Animal c = new Cat(); c的前面 类型写的是Animal 你就是Animal类型
        //既然 我们想让猫抓老鼠  那么 就强制转型被
        //在编译器的角度看c是Animal 类型我们强制转换(Cat)然后 用 新的Cat c1来接受新的对象
        Cat c1 = (Cat)c;
        c1.catchMouse();
        Dog d1=(Dog)d;
        d1.seeDoor();
        Pig p1 = (Pig)p;
        p1.sleep();
        Tiger t1 = (Tiger)t;
        t1.eat();
        //能把老虎转成猫吗?
        Cat c2 = (Cat)t;
        c2.catchMouse();//通过了,再次证明编译器死板
        //跑起来报错Exception in thread "main" java.lang.ClassCastException: com.bjsxt.oop.polymorphism.Tiger cannot be cast to com.bjsxt.oop.polymorphism.Cat
        //at com.bjsxt.oop.polymorphism.Test.main(Test.java:59)
        //老虎不能转成猫
    }
}

 打印一下

喵喵喵
汪汪汪
吭哧吭哧
吼吼吼
猫抓老鼠
狗看门
猪在睡觉
老虎在吃饭

显然,这么做比较繁琐 ,不如做个逻辑判断,是啥就是啥。

 1     //由于最后面的对象转型太繁琐,索性做一个逻辑判断
 2     public static void testAnimalVoice(Animal a){
 3         a.voice();
 4         if(a instanceof Cat){
 5             ((Cat)a).catchMouse();
 6         }else if(a instanceof Dog){
 7             ((Dog)a).seeDoor();
 8         }else if(a instanceof Pig){
 9             ((Pig)a).sleep();
10         }else{
11             ((Tiger)a).eat();
12         }
13     }

当然 里面也得做强制转换,否则,编译器不认,通不过。

 1     public static void main(String[] args) {
 2          //运行时类型 由实际传入的对象类型决定
 3         /*父类引用指向子类对象
 4         Cat c = new Cat();
 5         Animal a = c;
 6         我们写成下面这样
 7         */
 8         Animal c = new Cat();
 9         Animal d = new Dog();
10         Animal p = new Pig();
11         Animal t = new Tiger();
12         testAnimalVoice(c);
13         testAnimalVoice(d);
14         testAnimalVoice(p);
15         testAnimalVoice(t);
16   }

打印看一下结果

喵喵喵
猫抓老鼠
汪汪汪
狗看门
吭哧吭哧
猪在睡觉
吼吼吼
老虎在吃饭

   对象转型可以使父类对象的引用可以指向子类对象,给程序带来了比较好的可扩展性:我们可以在一个方法的参数里面定义父类的引用,然后实际当中传的时候传的是子类的对象,然后我们再在方法里面判断这个传过来的子类对象到底属于哪个子类,然后再去执行这个子类里面的方法或者调用这个子类里面的成员变量,因此程序的可扩展性比单独定义好多个方法要好一些。