这是我参与更文挑战的第6天,活动详情查看: 更文挑战
说完继承,我们再来聊聊多态!
多态字面上解释,就是程序可以有多个运行状态。
既然是运行状态,那其实更多的是强调方法的使用。
重载与覆写
方法在两种情况下使用会比较特别,一种是 overload(重载),overload 方法是本类内的新方法,方法名一样,但是参数的类型或数量不同。这种方法没有特殊的标识,通过类内方法是否重名判定。
另外一种就是 override(覆写),override 方法是继承关系下子类的新方法,方法签名和父类完全相同。这种方法都会有 @Override 注解的标识。
package cn.java4u.oo.polymorphism;
/**
* 动物
*
* @author 蜗牛
* @from 公众号:蜗牛互联网
*/
public class Animal {
/**
* 与 eat(String food) 重载
*/
public void eat() {
System.out.println("Animal.eat");
}
/**
* 与 eat() 重载
*
* @param food 食物
*/
public void eat(String food) {
System.out.println("Animal.eat: " + food);
}
/**
* 覆写
*
* @return 字符串
* @see java.lang.Object#toString
*/
@Override
public String toString() {
return "Animal " + super.toString();
}
}
举个例子,Animal 类里两个 eat 方法就互为重载方法,toString 方法就是相对于父类方法 java.lang.Object#toString 的覆写方法。
多态就发生在覆写这种场景下。针对某个类型的方法调用,它真正执行的方法取决于运行时期实际类型的方法。比如下面这段代码,当声明类型为 Object ,初始化类型为 Animal 时,你觉得输出的是 Animal 的 toString 方法,还是 Object 的 toString 方法?
package cn.java4u.oo.polymorphism;
/**
* @author 蜗牛
* @from 公众号:蜗牛互联网
*/
public class PolymorphismTest {
/**
* 打印对象
*
* @param scene 打印场景
* @param obj obj
*/
public static void printObjectString(String scene, Object obj) {
System.out.println(scene + ": " + obj.toString());
}
public static void main(String[] args) {
// 父类引用初始化父类对象并打印
Object rootObj = new Object();
printObjectString("父类引用初始化父类对象", rootObj);
// 子类引用初始化子类对象并打印
Animal animal = new Animal();
printObjectString("子类引用初始化子类对象", animal);
// 父类引用初始化子类对象并打印
Object animalWhenParentRef = new Animal();
printObjectString("父类引用初始化子类对象", animal);
}
}
答案是子类 Animal 的 toString 方法!
父类引用初始化父类对象: java.lang.Object@60e53b93
子类引用初始化子类对象: Animal cn.java4u.oo.polymorphism.Animal@5e2de80c
父类引用初始化子类对象: Animal cn.java4u.oo.polymorphism.Animal@5e2de80c
实际类型为 Animal 引用类型为 Object ,调用 toString 方法时,实际上是子类的。因此我们可以得出结论:Java 的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。这种特性就是多态!
你会发现 printObjectString 方法的第二个参数,即便声明的是 Object ,实际运行的时候,却可以是它的子类覆写方法。
至此,我们也理出了 Java 实现多态三要素,那就是 继承、覆写和向上转型。即两个类之间有继承关系,某个类覆写了父类的某个方法,方法的引用会指向子类的实现处。
总结
面向对象语言这个系列呢,我们分析了面向对象的概念和思想。接着基于面向对象的特征:抽象、封装、继承和多态,我们又详细的分析了在 Java 中的体现方式,并伴有很多样例代码辅助学习。看完这个系列,想必你对面向对象这个东西会有更全面的了解。
好啦,本系列的分享就到这里,如果各位喜欢我的分享,请务必三连,点赞,分享,收藏,关注我,这会对我有非常大的帮助。
我们下期再见。