引言
java的三大特性:封装,继承和多态、
封装和继承也是为多态服务的。
多态即为事物在运行的过程中呈现不同的状态。举个简单的例子,对于键盘上的按键组成的快捷键,同一个快捷键在不同的应用中对应着不同的操作。
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的作用:消除类型之间的耦合关系。
多态的三个前提
1、要有继承
2、要有重写,子类重写父类的方法
3、父类引用指向子类对象
示例代码
父类Animal
class Animal{
int weight = 50;
static int age = 20;
public void eat()
{
System.out.println("Animal eat...");
}
public static void sleep()
{
System.out.println("Animal sleep...");
}
public void run()
{
System.out.println("Animal run...");
}
}
子类Dog
class Dog extends Animal{
int weight = 30;
static int age = 10;
public void eat()
{
System.out.println("Dog eat...");
}
public static void sleep()
{
System.out.println("Animal sleep...");
}
public void watchDoor()
{
System.out.println("Dog watch the door...");
}
}
测试类Test
class Test
{
public static void main()
{
Animal animal = new Dog();
animal.eat();
animal.sleep();
animal.run();
//以下这两句是会报错的
//animal.watchDoor();
//System.out.println("name="+animal.name);
System.out.println("weight="+animal.weight);
System.out.println("age="+animal.age);
}
}
以上的代码充分体现了多态的三个前提:
1、要有继承
Dog继承了Animal
2、要有重写、
Dog类重写了静态方法sleep(),和非静态方法eat()
3、父类引用指向子类对象
Animal animal = new Dog();
在堆内存空间上开辟了空间,存放子类Dog的对象。并把在栈空间上存放的父类Animal类的引用指向了这个Dog对象
运行结果:
多态成员访问的特点
成员变量
编译看左边(父类),运行看左边(父类)
非静态成员方法
编译看左边(父类),运行看右边(子类)
静态方法
编译看左边(父类),运行看左边(父类)
多态好处
1.可替换性(substitutability)
多态对已存在代码具有可替换性。例如,多态对Dog类工作,对其他任何动物,如猫、猪等,也同样工作。
2.可扩充性(extensibility)
多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)
多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性(flexibility)
它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)
多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要
多态弊端
不能使用子类特有的成员属性和成员方法
代码中出错的两句
animal.watchDoor();
System.out.println("name="+animal.name);
如果这里想要访问watchDoor()方法和name属性,则可以使用强制转换,这样animal就是Dog类型的引用了,指向的也是Dog对象,因此能够访问Dog类的所有成员变量和成员方法
代码如下:
Dog dog = (Dog)animal;
dog.watchDoor();
System.out.println("name="+dog.name);