动物王国的面向对象

转自:动物王国的面向对象


动物世界最近出现了两个动物, 不知道是从哪儿new 出来的。 
当他们在大街上走的时候, 我们只能看到两团迷雾,看不出来里边具体是什么动物, 幸好迷雾上方一直浮着一个标签: Animal 。
让我们知道他们应该是动物,不是怪物。

有一天,这两个家伙见面了, 我们暂时称呼他们A1 和A2 吧。
A1 : 哥们,咱俩这么像,你是谁啊

A2:  我一直想搞清楚我到底是谁,  我被new 出来的时候只知道我是个Animal 。

A1:  我也是, 我们一起研究下, 要不先看看Animal 的定义了啥吧

A2:  我看看, 有个 int age;  变量,  我访问下试试  , System.out.println(A2.age)   , 返回4, 看来我4岁了

A1:  这有啥用,  这个Animal 不是还有个函数吗? 能够获得最喜欢的食物,  不过它返回“不知道”, 这实在是太搞笑了。
public String getFavoriteFood(){
        return "不知道";
}

A2:  恩, 确实搞笑, 要不我调用一下试试?  A2.getFavoriteFood()  , 它竟然返回了“鱼”!, 这是怎么回事?  也许我是一只猫?

A1: 不可能吧, 我也试试, A1.getFavoriteFood() ,  天哪, 它返回了“骨头”!  难道我是狗吗?
(A1,A2这两个家伙不知道,其实这里是“多态”起了作用)

A2 :  要不我试试转型成猫 ? 慢着, 我先判断一下 (A2 instanceof Cat) , 是true , 好了,转型!  Cat cat = (Cat) A2   
        (神奇的事情发生了, A2 周围的迷雾消失了, A2真的是一只猫!)

A1:  原来如此,  我也来转型 , Dog dog = (Dog)A1    , 果然我是一只狗啊。
(两个现了原型的家伙非常高兴) 

Cat:  Dog 兄,  我想起来了, 他们的确是通过 new Cat() 把我new 出来的, 但是给我赋给了 Animail a2 = new Cat() , 不知道他们为啥这么干?

Dog: Cat 弟, 别管这么多了, 走了半天,肚子饿了, 我们找点东西吃吧。 

Cat:  你自己不就有个eat方法吗? public String eat(Food d);

Dog :  是啊, 可是Food 从那里来, 得餐馆才能提供啊
(两个家伙往前走 ,找餐馆)

Cat :  看!前面有一家, 不过上面写着只允许兔子进入
public void enterGate(Rabbit r);

Dog :  让我试试能不能进去   enterGate(dog) ,  啊,编译错误

Cat :    你不会强制转型吗? 看我的,  Rabbit r = (Rabbit)cat;  还是编译错误。
(其实他们不知道,Java是个强类型语言,类型不同,是无法强制转型的)

Dog:  看,那里有个团队游客入口, 我们混进去吧:
    public void enterGat(List<Rabbit> rabbits){
        Iterator<Rabbit> iter = rabbits.iterator();
        while(iter.hasNext()){
            Rabbit r = iter.next();
            r.eat(food);
        }
    }

Cat :   好
List list = new ArrayList();
list.add(cat);
list.add(dog);
enterGate(list); 

Dog: 没有编译错误, 竟然混进来了, 开吃吧

Cat : 怎么回事? 运行时还是出来异常啊。。。  
java.lang.ClassCastException: Cat cannot be cast to Rabbit

Dog : 走吧,换一家, 唉,这家只允许老虎入内, 这破程序是谁写的啊?

CAT:   看看前面那家,多大啊, 几乎所有的动物都能进去啊, 你看哈巴狗和波斯猫正在往里边跑呐。

Dog :   恩, 它的门上写着动物都可以入内,  我们进去试试吧
public void enterGate(Animal a)

(Dog和Cat都顺利的进了门, 因为他们都是“Animal”, 但是进去后就发现, 所有的动物都是一团迷雾, 再也认不出谁是谁了, Dog和Cat又变成了A1和A2)

A2 :  Dog兄, 你还在吗? (没有回音)  
A2:   恩,我是谁啊?

服务员:  别琢磨了, 你是第一次来吧, 新人都有这个毛病, 老是爱琢磨自己的具体类。    请提供你最喜欢的食物?

A2:     "鱼" (调用getFavoriteFood()方法

服务员: "稍等,鱼马上就来"

A2:“你也不问问我到底是谁吗?”

服务员: 我不管你是谁,只要你是Animal 就行, 你不是有个eat方法吗?  我们这个餐馆,使用的是“面向接口编程, 而不是面向具体类编程”, 要不然,每个动物都判断一下, 我们不亏死了。 

A2:  奥,我有点明白那帮家伙把我new 出来以后,只是给我贴上Animal标签的原因了。