面向对象有三大特性:继承、封装、多态。
继承与封装都比较容易理解,那么应该理解多态呢?
多态,其实就是一个事物的多种形态。例如,一只猫,你可以叫它一只猫,也可以叫它一只动物。
多态在java中是怎么体现的呢?
需要满足三个前提:
1.要有继承关系
2.要有方法重写
3.父类引用指向子类对象
示例:
public class Demo { public static void main(String[] args){ Animal a = new Cat(); // 父类引用子类对象。猫可以是动物 a.eat(); } } class Animal{ public void eat(){ System.out.println("动物吃东西"); } } class Cat extends Animal{ // 有继承关系 public void eat(){ // 有方法重写 System.out.println("猫吃鱼"); } }
这就是多态的经典例子。最重要的是父类引用子类对象。
1.成员变量
编译看左边,运行看左边
public class Demo2 { public static void main(String[] args){ Dad d = new Son(); System.out.println(d.num); } } class Dad{ int num = 10; public void show(){ System.out.println("Dad"); } } class Son extends Dad{ int num = 20; public void show(){ System.out.println("Son"); } }
输出结果是10
2.成员方法
编译看左边,运行看右边
public class Demo2 { public static void main(String[] args){ Dad d = new Son(); d.show(); } } class Dad{ int num = 10; public void show(){ System.out.println("Dad"); } } class Son extends Dad{ int num = 20; public void show(){ System.out.println("Son"); } }
输出结果是:Son
3.静态方法
编译看左边,运行看左边
public class Demo2 { public static void main(String[] args){ Dad d = new Son(); d.show(); // 相当于Dad.show() } } class Dad{ int num = 10; public static void show(){ System.out.println("Dad"); } } class Son extends Dad{ int num = 20; public static void show(){ System.out.println("Son"); } }
输出结果:Dad
1.向上转型。
向上转型其实就是父类引用子类对象。
public class Demo2 { public static void main(String[] args){ Dad d = new Son(); // 向上转型 } } class Dad{ int num = 10; public void show(){ System.out.println("Dad"); } } class Son extends Dad{ int num = 20; public void show(){ System.out.println("Son"); } public void play(){ System.out.println("玩耍"); } }
2.向下转型。
如上面的例子所示,如果我们想要打印子类的num,调用子类的play()方法时,使用d.num打印的是父类的num值,而且d.play()直接出错了,因为父类没有play()方法,编译的时候不能通过。
有什么解决方案呢?(访问子类独有的属性与方法)
如果对象是Son类的对象就没有这些问题了。
所以我们要向下转型。(这就是多态的弊端)
示例:
public class Demo2 { public static void main(String[] args){ Dad d = new Son(); Son s = (Son) d; // 向下转型 System.out.println(s.num); s.play(); } } class Dad{ int num = 10; public void show(){ System.out.println("Dad"); } } class Son extends Dad{ int num = 20; public void show(){ System.out.println("Son"); } public void play(){ System.out.println("玩耍"); } }
输出结果:
20
玩耍
我们为什么要转型来转型去呢?直接Son s = new Son();不就好了吗?
别急,来看看多态的好处就知道了。
假如有这么一个场景。
class Animal{ public void eat(){ System.out.println("动物吃东西"); } } class Cat extends Animal{ // 有继承关系 public void eat(){ // 有方法重写 System.out.println("猫吃鱼"); } } class Dog extends Animal{ public void eat(){ System.out.println("狗吃骨头"); } }
如果你需要创建10个猫对象,并且调用eat()方法,原始做法是这样的:
public class Demo { public static void main(String[] args){ Cat c1 = new Cat(); c1.eat(); Cat c2 = new Cat(); c2.eat(); ...... }
然后你觉得很麻烦,你写了一个方法来改善它,
public class Demo { public static void main(String[] args){ method(new Cat()); method(new Cat()); } public static void method(Cat c){ c.eat(); } }
这时候,又有需求,你要创建10个Dog对象,并调用eat()方法。
你不得已,又写了一个方法:
public class Demo { public static void main(String[] args){ method(new Cat()); method(new Cat()); method2(new Dog()); method2(new Dog()); } public static void method(Cat c){ c.eat(); } public static void method2(Dog d){ d.eat(); } }
这时候,又有一大堆需求,又新增猪类,鸡类,鸭类,继承Animal......你不再想写方法了。这时候多态的作用就来了。
多态改善后:
public class Demo { public static void main(String[] args){ method(new Cat()); method(new Cat()); method(new Dog()); method(new Dog()); } public static void method(Animal a){ a.eat(); } }
这就是多态的好处了,可以提高代码的扩展性。
开发的时候很少在创建对象的时候用父类引用指向子类对象,直接创建子类对象更方便,可以使用子类中特有的属性与方法。当作参数的时候用多态最好,因为扩展性强。
原文:https://www.cnblogs.com/chichung/p/10228991.html