目录
多态
重写
向上转型
类的多态性例子:
多态的优缺点
多态
所有的OOP语言都会有三个特征:
- 封装(点击可跳转)
- 继承(点击可跳转)
- 多态
多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。
在java中要实现多态,必须要满足如下几个条件,缺一不可:
- 必须在继承体系下;
- 子类必须要对父类中方法进行重写 ;
- 通过父类的引用调用重写的方法。
重写
继承我们已经知道了,那我们面临的第一个问题就是什么是重写?
重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值(返回类型满足父子关系也可以)和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
注:避免在构造方法中调用重写的方法。
方法重写的规则:
- 子类在重写父类的方法时,一般必须与父类方法原型一致:方法名,参数列表要完全一致;
- 被重写的方法返回值类型可以不同,但是必须是具有父子关系的;
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected,父类被static、private修饰的方法、构造方法都不能被重写;
- 重写的方法, 可以使用 @Override 注解来显式指定,有了这个注解能帮我们进行一些合法性校验。例如不小心将方法名字拼写错了 (比如写成 aet),那么此时编译器就会发现父类中没有 aet 方法,就会编译报错, 提示无法构成重写。
此时我们已经满足两点了还差最后一点。而第三点是通过父类的引用调用重写的方法。而要实现这一点就必须进行向上转型。
向上转型
向上转型就是为了实现代码通过父类的引用调用重写的方法。向上转型其实很简单
向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
语法格式:父类类型 对象名 = new 子类类型()
向上转型的使用场景:
- 直接赋值(上面的例子就是直接赋值)
- 方法传参
- 方法返回
向上转型的优点:让代码实现更简单灵活。
向上转型的缺陷:不能调用到子类特有的方法。
使用了向上转型之后就可以通过父类的引用调用重写的方法,而不是重写方法的就没法调用。
class Animal{
public String name = "花花";
public void eat(){
System.out.println(this.name+"正在吃饭");
}
}
class Dog extends Animal{
@Override
public void eat(){
System.out.println(this.name+"在吃狗粮");
}
public void a(){
System.out.println("hhh");
}
}
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
dog.eat();
//打印花花在吃狗粮
Animal dog2 = new Animal();
dog2.eat();
//打印花花正在吃饭
}
}
类的多态性例子:
class Animal{
public String name = "花花";
public void eat(){
System.out.println(this.name+"正在吃饭");
}
}
class Dog extends Animal{
@Override
public void eat(){
System.out.println(this.name+"在吃狗粮");
}
}
class Cat extends Animal{
@Override
public void eat(){
System.out.println(this.name+"在吃猫粮");
}
}
public class Test {
public static void fun(Animal arr){
arr.eat();
}
public static void main(String[] args) {
//数组的每个成员都会发生向上转型
Animal[] arr = {new Dog(),
new Cat()};
//此时就会发现调用同一个方法fun()会有两种结果
fun(arr[0]);
fun(arr[1]);
}
}
多态的优缺点
- 能够降低代码的 "圈复杂度", 避免使用大量的 if - else;
什么叫 "圈复杂度" ?
圈复杂度是一种描述一段代码复杂程度的方式。一段代码如果平铺直叙,那么就比较简单容易理解。而如果有很多的条件分支或者循环语句,就认为理解起来更复杂;
因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数,这个个数就称为 "圈复杂度"。如果一个方法的圈复杂度太高, 就需要考虑重构。
- 可扩展能力更强;
- 多态缺陷:代码的运行效率降低。