Java面向对象编程·下_在main() 方法中使用父类引用指向子类对象的方式(向上转型),分别使用person类和wo

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取


另外, 针对重写的方法, 可以使用 `@Override` 注解来显式指定.



// Bird.java
public class Bird extends Animal {
@Override
private void eat(String food) {

}
}


有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.


我们推荐在代码中进行重写方法时**显式加上** @Override 注解.



> 
> 关于注解的详细内容, 我们会在后面的章节再详细介绍.
> 
> 
> **小结**: 重载和重写的区别.
> 
> 
> 



> 
> **体会动态绑定和方法重写**
> 
> 
> 上面讲的动态绑定和方法重写是用的相同的代码示例.
> 
> 
> 事实上, 方法重写是 Java 语法层次上的规则, 而动态绑定是方法重写这个语法规则的底层实现. 两者本质上描述的是相同的事情, 只是侧重点不同.
> 
> 
> 


### 3.4理解多态


有了面的向上转型, 动态绑定, 方法重写之后, 我们就可以使用 **多态(polypeptide)** 的形式来设计程序了.我们可以写一些只关注父类的代码, 就能够同时兼容各种子类的情况.


代码示例: 打印多种形状



class Shape {
    public void draw() {
        // 啥都不用干
    }
}
class Cycle extends Shape {
    @Override
    public void draw() { System.out.println("○");
    }
}
class Rect extends Shape {
    @Override
    public void draw() {
        System.out.println("□");
    }
}
class Flower extends Shape {
    @Override
    public void draw() {
        System.out.println("♣");
    }
}
/我是分割线// 

// Test.java
public class Test {
public static void main(String[] args) {
Shape shape1 = new Flower();
Shape shape2 = new Cycle();
Shape shape3 = new Rect();
drawMap(shape1);
drawMap(shape2);
drawMap(shape3);
}
// 打印单个图形
public static void drawShape(Shape shape) {
shape.draw();
}
}


在这个代码中, 分割线上方的代码是 **类的实现者** 编写的, 分割线下方的代码是 **类的调用者** 编写的.


当类的调用者在编写 drawMap 这个方法的时候, 参数类型为 Shape (父类), 此时在该方法内部并**不知道**, **也不关注**当前的 shape 引用指向的是哪个类型(哪个子类)的实例. 此时 shape 这个引用调用 draw 方法可能会有多种不同的表现(和 shape 对应的实例相关), 这种行为就称为 **多态**



> 
> 多态顾名思义, 就是 “一个引用, 能表现出多种不同形态”
> 
> 
> 举个具体的例子. 汤老湿家里养了两只鹦鹉(圆圆和扁扁)和一个小孩(核弹). 我媳妇管他们都叫 “儿子”. 这时候我对我媳妇说, “你去喂喂你儿子去”. 那么如果这里的 “儿子” 指的是鹦鹉, 我媳妇就要喂鸟粮; 如果这里的 “儿子” 指的是核弹, 我媳妇就要喂馒头.
> 
> 
> 那么如何确定这里的 “儿子” 具体指的是啥? 那就是根据我和媳妇对话之间的 “上下文”.
> 
> 
> 代码中的多态也是如此. 一个引用到底是指向父类对象, 还是某个子类对象(可能有多个), 也是要根据上下文的代码来确定.
> 
> 
> PS: 大家可以根据汤老湿说话的语气推测一下在家里的家庭地位
> 
> 
> 


**使用多态的好处是什么?**


**1) 类调用者对类的使用成本进一步降低.**


* 封装是让类的调用者不需要知道类的实现细节.
* 多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可.


因此, 多态可以理解成是封装的更进一步, 让类调用者对类的使用成本进一步降低.


这也贴合了 <<代码大全>> 中关于 “管理代码复杂程度” 的初衷.


**2) 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else**


例如我们现在需要打印的不是一个形状了, 而是多个形状. 如果不基于多态, 实现代码如下:



public static void drawShapes() {
Rect rect = new Rect();
Cycle cycle = new Cycle();
Flower flower = new Flower();
String[] shapes = {“cycle”, “rect”, “cycle”, “rect”, “flower”};

for (String shape : shapes) {
    if (shape.equals("cycle")) {
        cycle.draw();
    } else if (shape.equals("rect")) {
        rect.draw();
    } else if (shape.equals("flower")) {
        flower.draw();
    }
}

}


如果使用使用多态, 则不必写这么多的 if - else 分支语句, 代码更简单.



public static void drawShapes() {
// 我们创建了一个 Shape 对象的数组.
Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),
new Rect(), new Flower()};
for (

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值