众所周知,Java是一个面向对象(OOP)的编程语言,面向对象语言有封装、继承、多态这三大基本特征。下面我将通过这篇文章来告诉你什么是多态,多态存在的条件,以及我对于多态的理解,对于向上转型向下转型存在的原因的解释。
举例
猫和狗都是动物,它们之间既有共同点,又有自己的特点。你让猫和狗一起叫,它们都会叫,但是叫声不一样,这就是生活中的多态。
什么是多态?
多态,是指同一行为具有多种表现形式或形态的能力。父类引用指向子类的对象,调用方法时只能调用子类重写的方法,而如果想要调用子类新增的方法,则需要强制类型转换成子类;在运行期间能根据对象的实际类型自动调用相对应的方法;这就是多态。
多态存在的三个必要条件
- 继承
- 重写(Override)
- 父类引用指向子类对象(向上转型)
Java多态性的表现
1. 方法的多态性
编译过程中的多态表现为函数的重载(Overload),运行时的多态表现为函数的重写(Override)。
2. 对象的多态性
下面通过例子来感受下java对象的多态性
class Animal{//父类
void cry(){
System.out.println("动物叫");
}
void sleep(){
System.out.println("动物睡觉");
}
}
class Dog extends Animal{//子类继承了父类
void keepHouse(){//子类新增的方法
System.out.println("狗看家");
}
void cry(){//覆盖父类的方法
System.out.println("狗叫");
}
}
class Cat extends Animal{//子类
void play(){//子类新增的方法
System.out.println("猫玩耍");
}
void cry(){//覆盖父类的方法
System.out.println("猫叫");
}
}
public class demo1 {
public static void main(String[] args) {
//父类引用指向子类对象
Animal pet=new Dog();
pet.cry();//调用父类和子类共有的方法cry(),注意这里调用的是覆盖后的cry()方法
pet.sleep();//调用父类和子类共有的方法
Dog d=(Dog)pet;//将pet强制类型转换(从Animal到Dog),这样就可以调用子类自己(新增)的方法;
d.keepHouse();//调用子类新增方法
}
}
-
多态一定是采用向上转型的方法来定义对象pet的,父类只能使用子类与父类共有的方法(也就是只能使用子类覆盖的方法),而如果想用子类的所有属性的话,就强制转换成子类(通过向下转型)就好了。
-
这个实例中定义对象pet使用的是向上转型的方式是
Animal pet=new Dog();
,那么大家肯定有一个疑问:为什么不用最方便的Animal pet=new Animal();
的方式来定义呢?原因就是使用后者的话代码非常的僵硬,可扩展性就没有了,所以可以看出多态的一个优点:可扩展性强。 -
注意
- 不能采用如下方式调用,因为只能调用子类与父类共同的方法(子类重写的方法),不能调用子类新增方法keepHouse()
pet.keepHouse();
- 向上转型
定义方式:父类类型 变量名=new 子类类型();
Animal pet=new Dog();//父类引用指向子类对象
- 向下转型
向上转型是向下转型的必要条件
Animal pet=new Dog();//向上转型
Dog d=(Dog)pet;//强制类型转换(Animal->Dog)
public class demo2 {
public static void main(String[] args) {
Animal pet;//声明父类对象
pet=new Animal();
pet.cry();
pet=new Dog();//将子类对象给父类
pet.cry();
pet=new Cat();//将子类对象给父类
pet.cry();
}
}
-
通过一个变量去调用一个函数,我们只是写了一句话,并不会判断变量实际的类型是什么,不需要switch case,也不需要if else,因为只要写上这句话,系统就会自动调用该类所对应的函数
- 例如:所有的Animal类中都有cry()函数,对于一个继承了Animal的dog,它是一个Animal,那么它就一定能cry,我不关心你到底是怎么cry的,因为java存在一种机制能够找到正确的cry。
-
测试类demo2运行结果
多态的优点
- 可扩展性
增加新的子类不影响已存在类的运行和操作,方便代码的维护。 - 灵活性
它在应用中体现了灵活多样的操作,提高了使用效率。 - 简化性
简化对应用软件的代码编写和修改过程,尤其在处理大量代码需要重复的情况,可以有效避免代码臃肿的问题,这也是继承的优点。