多态可以理解为:事物在运行中存在不同的状态。
多态存在的3个前提条件:
1.要有继承关系。
2.子类要重写父类方法。
3.父类的引用指向子类对象。
弊端就是:不能使用子类特有的成员属性和子类特有的成员方法。如果非要用到不可,可以强制类型转换。
下面以具体代码来说明
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Animal { int num = 1; static int age = 2; public void eat() { System.out.println("动物吃饭"); } public static void run() { System.out.println("动物在奔跑"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Dog extends Animal { int num = 100; static int age = 101; String name = "HotDog"; @Override public void eat() { System.out.println("狗啃骨头"); } public static void run() { System.out.println("狗在奔跑"); } public void drink() { System.out.println("狗在喝水"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class Test { public static void main(String[] args) { Animal animal = new Dog(); animal.eat(); animal.run(); System.out.println(animal.num); System.out.println(animal.age); } }
|
运行结果:
从运行结果可以总结多态成员访问特点:
成员变量
编译看左边(父类),运行看左边(父类);
成员方法
编译看左边(父类),运行看右边(子类);动态绑定。
静态方法
编译看左边(父类),运行看左边(父类);(静态和类相关,算不上重写,所以还是访问左边)
只有非静态的成员方法,编译看左边,运行看右边。
接下来看多态的弊端 :不能使用子类特有的属性和方法。
可以通过代码得知子类Dog有一个特有属性 String name = “HotDog”;
并且还有一个drink()方法,但是在测试类中调用子类的方法和输出子类特有的变量就会报错。
如果我们想使用子类的特有方法,那么就必须把这个父类指向子类的对象强转成子类的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Test { public static void main(String[] args) { Animal animal = new Dog(); animal.eat(); animal.run(); System.out.println(animal.num); System.out.println(animal.age); Dog dog = (Dog) animal; dog.drink(); System.out.println(dog.name); } }
|
执行Dog dog = (Dog) animal;后,dog就指向最开始在堆内存里创建的Dog对象了。多态的魅力就在于此。