前言
多态如同编程世界的变色龙————同一段代码,却能因环境不同展现出万般形态...
多态的概念
那么我们抛出一个问题:什么是多态?
简单的回答即是:同一操作作用于不同对象,产生不同行为。
但是这并不能很好的理解多态的定义,如果想成为一名优秀的程序员,仅仅解释成这一简单的话是不够的,需要我们更加深入的探讨,并实际运用通俗易懂的例子是必要的。
通俗解释
想象你有一个万能遥控器,上面有个“开关”按钮。这个遥控器可以控制不同的电器:
-
当对着空调按 → 空调“滴”一声开始制冷
-
当对着电视按 → 电视“嗡”一声亮屏播放
-
当对着音响按 → 音响“咚”一声播放音乐
这就是多态的本质:
-
同一个操作指令(按下“开关”)
-
作用在不同对象上(空调、电视、音响)
-
触发不同的具体行为(制冷、播放节目、播放音乐)
构成多态的条件
-
向上转型
向上转型是指将子类对象赋值给父类引用的过程
我们一般实例一个对象的时候,通常都是用同种类型,比如
Bear bear = new bear();
向上转型则是 把子类对象的引用给到父类
Animal bear = new bear();
向上转型一般有三种方式
-
直接赋值
-
参数的传递
-
返回值
public static void main1(String[] args) {
Animal animal = new bear();
}
public static void fun1(Animal animal){
animal.eat();
}
public static void main2(String[] args) {
bear bear = new bear();
fun1(bear);
}
public static Animal fun3(){
return new bear();
}
那么有向上转型,就会有向下转型
向下转型有个特点:需要强制转换(这里我们不做过多探讨)
那么我们可以总结向上转型的特点:
-
自动完成:无需强制转换,直接赋值
-
只能调用父类方法:通过父类引用只能访问父类中定义的方法,不能调用子类特有的方法
-
实际的对象还是子类的:(就像把一只猫装进“动物”盒子,它本质上还是猫)
-
重写
重写则是子类对父类原有的方法进行重新定义,也叫覆写,以达到在执行同一件事物的时候产生不同的现象,他与动态绑定息息相关
以Animal为父类,Bear为子类来举例:Animal定义了一个方法为eat,我们在子类Bear中对父类的eat方法进行重写
public class Animal {
public String name;
public int age;
String color = "white";
public void eat(){
System.out.println(this.name+"正在吃饭");
}
}
public class bear extends Animal{
public int numPow = 2;
public bear(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃蜂蜜");
}
}
重写要求
- 必须存在于继承关系中
- 重写时的参数列表,返回值,顺序,方法名必须一样
- 子类方法的访问权限要大于或等于父类方法的访问权限
例如父类的方法的访问权限是protected,则子类重写时的访问权限只能是protected/public
- 最好用@Override来注解,检查是否成功重写,也方便后续的代码的更改
除此之外还有一种写法,这种叫协变类型
注意事项
- 被static修饰的不可重写(静态方法是属于类的,不是实例的)
- 被final修饰的不可重写
- 被private修饰的不可重写
与重载的区别
-
重写:用于子类定制父类行为,实现多态(运行时决定调用)
-
重载:用于同一类中提供方法的不同版本,简化调用(编译时决定调用)
-
动态绑定
public class bear extends Animal{
public int numPow = 2;
public bear(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃蜂蜜");
}//重写方法
}
public class Test {
public static void main(String[] args) {
Animal bear = new bear("xiongda",12,"brown");
bear.eat();//调用了子类的重写方法
}
}
- 通过了上述的代码,我们通过父类的引用,只能调用父类的方法
- 此时子类对父类的方法进行了重写
- 父类引用了引用子类的对象,通过父类的引用,调用了这个子类的重写方法
此时把这种现象叫做动态绑定
结语
掌握多态,能提升我们的开发效率,避免我们用过多的if语句,降低模块依赖,提升可维护性,而且新增子类时不需要修改原有的代码逻辑。
这只代码变色龙最终教会我们:真正的适应性不是改变本色,而是在坚守核心的同时,学会用不同的皮肤来感知世界。子类不必活成父类的复刻,正如人生不该只有一种正确的打开方式。
希望大家看到文章能有所收获,祝大家身体健康,变得更好。