多态
多态从字面上讲很简单, 就是一个对象, 多种形态. 这个东西有什么用, 我们来看一段代码.
package com.xyq.bao; public class Dog{ public void eat(){ System.out.println("狗吃骨头"); } } package com.xyq.bao; public class Cat{ public void eat(){ System.out.println("猫吃鱼"); } } package com.xyq.bao; public class Person{ public void feedCat(Cat c){ c.eat();// 让猫吃 } public void feedDog(Dog d){ d.eat();// 让狗吃 } } package com.xyq.bao; public class Test { public static void main(String[] args) { Person p = new Person(); Cat c = new Cat(); Dog d = new Dog(); p.feedCat(c); f.feedDog(d); } }
大家发现没有. 这个人啊. 好累哦. 喂猫, 喂狗的. 是吧, 但是如果再来一种动物怎么办? 比如养了一只鹦鹉.
package com.xyq.bao; public class Parrot{ public void eat(){ System.out.println("鹦鹉吃蔬菜"); } }
这时你发现, 人养不了鹦鹉. 想要养鹦鹉. 必须再添加一个方法. 是吧. 家里养多少动物就得写几个方法. 太麻烦了. 而且. 在喂猫, 喂狗的时候. 内部的代码逻辑基本是一样的. 那能不能简化一下. 可以的. 用多态. 同一个对象, 多种形态, 你想啊. 猫是不是可以当成动物来看, 猫是一种动物, 猫自然而然可以当动物来看啊. 那在java里这个就要写继承了. 对吧.
package com.lewen.opp; public class Animal { public void eat() { System.out.println("动物吃东西"); } } package com.lewen.opp; public class Cat extends Animal { public void eat(){ System.out.println("猫吃鱼"); } }
然后. 我们创建猫的时候就可以这样干.
package com.lewen.opp; public class Client { public static void main(String[] args){ Cat c = new Cat(); Animal ani = new Cat(); } }
把子类的对象赋值给父类的变量. 这个在java里被称为向上转型.
向上转型的优点: 自动转型. 把不相关的东西转化成相同的数据类型. 猫, 狗, 鹦鹉都当成动物来看~~
这样, 作为铲屎官的我就舒服了
统一喂这个动作,而不是来一个动物,去创建一个喂该动物的方法
package com.lewen.opp; public class Zookeeper { public void feed(Animal ani){ ani.eat(); } }
测试:
package com.lewen.opp; public class Test { public static void main(String[] args) { Zookeeper p = new Zookeeper(); Animal c = new Cat(); Animal d = new Dog(); p.feed(c); p.feed(d); } }猫吃鱼狗吃鱼
OK. 没有问题.
我们现在看到的这个就是多态性. 说白了. 不管你把怎么转型. 在执行的时候. JVM会自动去判断这个对象到底是什么的. 这个过程被称为动态数据类型绑定.
多态的现象: 父类的引用执行了子类中的方法
ani.eat(); // ani是父类的引用, eat()运行的时候执行的是子类中的方法.
多态的三个要素:
- 要有继承关系
- 要重写
- 要向上转型
优点: 让程序有超强的可扩展性.
补充一个小知识点:
我们之所以称为向上转型, 是因为在继承体系里. 父类一般画在上面, 子类在下面. 因为按照先后顺序来讲, 肯定是先有父类, 然后才有子类的. 所以把子类的对象赋值给父类的变量. 这个叫向上转型.
那既然有向上转型, 就一定有向下转型.
你把猫转型成了动物. 那站在动物的角度去看猫就必然会屏蔽掉猫自己特有的一些特点. 比如, 抓老鼠. 你可以说猫抓老鼠, 但你不能说动物抓老鼠. 所以. 向上转型之后, 你就不能执行子类中特有的一些方法了. 那如果非要执行怎么办? 把动物再变回猫呗. 但是, 问题来了. 你把猫转成动物是OK的. 安全的. 但是, 你把动物变成猫. 这就有可能会出问题. 万一这个动物不是猫怎么办. 所以java要求. 如果你想把父类的变量转化回子类的类型. 就必须要强转
(转化之后的类型) 变量
package com.lewen.opp; public class Test { public static void main(String[] args) { Zookeeper p = new Zookeeper(); Animal c = new Cat(); Cat cz = (Cat) c; //强转 Animal d = new Dog(); p.feed(c); p.feed(d); } }