目录
🐲 1.理解多态的概念
要理解多态,我们可以先看这张图片
🟧图片中是支付这个行为,通过不同的APP去支付,就会有不同的状态。
而多态也是这个道理,
🟪多态是同一个行为具有多个不同表现形式或形态的能力。
🟫多态就是同一个接口,使用不同的实例而执行不同操作
🐲 2.多态存在的三个必要条件
在java中要实现多态,就必须满足这三个条件:
🟥(1)必须继承的体系里面
🟦(2)通过父类的引用调用重写的方法
🟧(3)子类必须要对父类中方法进行重写
🐲 3 重写和重载的区别
⚜️要比较区别就要明白先明白什么叫做重写?
我们先看这个例子
在子类和父类中,都有eat这个方法
通过观察,发现
🟥(1)子类和父类的方法返回类型一样,
🟧(2)方法的方法名一样
🟦(3)还有方法的参数类型,个数,顺序也相同
⚜️观察子类和父类的这两个方法,感觉都几乎一样,我想试一试,看有些地方变一下出错不
我给把父类的成员方法变成静态的,结果很显然报错了,所以
🟪(4)static方法不能被重写
⚜️ 那么前面的访问修饰符能否被修改呢
我把父类的访问限定符修改成了private后注解报错了
🟫(5)private修饰的方法 不能被重写
⚜️然后我继续修改访问限定符,父类和子类的都试着修改了一下,发现了一个比较有意思的现象
因为访问限定符的权限是这样的
如果子类访问权限大于等于父类,就可以重写,比如看这个
🟪(6)子类访问修饰符权限要大于等于父类
⚜️ 正当我以为,重写满足这些条件足够了,查询一番后,发现返回类型竟然也可以不同
🟩(7)被重写的方法返回值类型可以不同,但是必须是具有父子关系的
⚜️总结一下满足重写的条件
🟥(1)子类和父类的方法返回类型一样,
🟧(2)方法的方法名一样
🟦(3)还有方法的参数类型,个数,顺序也相同
🟪(4)static方法不能被重写
🟫(5)private修饰的方法 不能被重写
🟪(6)子类访问修饰符权限要大于等于父类
🟩(7)被重写的方法返回值类型可以不同,但是必须是具有父子关系的
⚜️这个再提个小建议,
比如,你写的时候将方法名拼写错了,那么编译器就会发现父类中没有这个方法,就会编译报错,不能构成重写
⚜️下面进行重写和重载简单的比较
方法重写是子类和父类的一种多态性表现
方法重载是一个类的多态性表现
区别点 | 重载 | 重写 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
访问限定符 | 可以修改 | 一定不能做更严格的限制 |
⚜️ 这里再说一个在重写中发生的动态绑定
🟧动态绑定:就是在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。
🐲 4.静态绑定和动态绑定
静态绑定
:也称为前期绑定
(
早绑定
)
,即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。动态绑定
:也称为后期绑定
(
晚绑定
)
,即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。
🐲 5.理解向上转型和向下转型
🦄 5.1 向上转型
⚜️先理解什么叫向上转型
🟧子类引用的对象转换为父类类型称为向上转型。
再通俗的讲,就是
🟩创建一个子类对象,将其当做父类对象来使用
⚜️看一下语法格式吧
父类类型 对象名 = new 子类类型();
⚜️直接上代码例子
class Animal{
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat() {
System.out.println(name + " 正在吃饭!");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void bark() {
System.out.println(getName()+" 正在狗叫!");
}
}
class Bird extends Animal{
public Bird(String name, int age) {
super(name, age);
}
public void fly() {
System.out.println(getName()+" 正在飞翔!");
}
}
public class Test01 {
public static void main(String[] args) {
Animal animal = new Bird("老鹰",3);
animal.eat();
}
}
}
⚜️分析一下吧
向上转型发生在三种情况下:
🟪(1)直接赋值
🟦(2)方法传参
🟩(3)方法返回
⚜️这里再分析一下向上转型的优缺点:
🟩优点:让代码实现更简单灵活
比如说方法传参,如果不能用向上转型的话,那就得用一个具体的类来接收,那这个方法就得写成多个方法。
🟧缺点:不能调用到子类特有的方法
🦄5.2 向下转型
⚜️ 但向下转型一般不用,这是因为不安全,比如
⚜️这里编译过程没报错,但运行就报错了,
⚜️那如果像这样的,还是想使用向下转型呢,那就要判断一下了
⚜️所以向下转型是什么,你现在理解了吗
🟪可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换。最好再使用一下Instanceof 来判断一下
⚜️ 向下转型和向上转型关系理解
🐲 6.多态的优缺点
⚜️使用多态的优点
🟥能够降低代码的圈复杂度
🤠我对于圈复杂的理解就是,一段代码的复杂程度
如果描述事情,用很多的条件分支或者循环语句,这就理解比较复杂。
我们一个尽量让代码更容易理解,平铺直叙一些,这就可以考虑使用多态
比如这个例子,描述图形的,这里只写了几种图形还看不出什么,如果写的特别多的情况下,用分支语句显然就不合适了
class Shape {
public void draw(){
System.out.println("画图形!");
}
}
class Rect extends Shape{
@Override
public void draw() {
System.out.println("♦");
}
}
class Cycle extends Shape{
@Override
public void draw() {
System.out.println("●");
}
}
}
public class Test02 {
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
Rect rect = new Rect();
Cycle cycle =new Cycle();
drawMap(rect);
drawMap(cycle);
}
}
🟧可扩展性强
比如说给这个里面再添加一种图形
使用多态 ,只需添加就可以了
而如果使用分支语句的话,那就要重新考虑判断条件了,可能之前写的都要修改,比较麻烦
优点主要就是这两个,其实还有一些别的优点,比如:
接口性,可替换性 … …
⚜️多态的缺点:
🟫代码的运行效率降低。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/87365.html