OOP 概述与抽象
OOP 概述与抽象
目标:理解面向机器 → 面向过程 → 面向对象三种范式的演进;掌握类、对象、属性、方法、封装、继承、多态七个基本概念;会用「抽象」把现实实体映射为类(属性 + 方法);理解
new之后堆与栈上各存什么。
一、三种编程范式
程序的本质是「用机器处理数据」。不同范式回答「数据放哪、怎么算」的方式不同:
| 范式 | 组织方式 | 数据保护 | 生活类比 |
|---|---|---|---|
| 面向机器 | 直接管地址与指令,门槛高、易错 | 无——谁都能改内存 | 大通铺:十几人挤一间,丢东西常见 |
| 面向过程 | 拆成函数/模块,顺序执行;模块间共享全局数据 | 弱——数据对其他模块完全开放,被误改难排查 | 4 人间:比通铺好,但室友互取物品难免 |
| 面向对象 | 拆成对象,数据与操作封装在一起,事件触发、可多线程协作 | 强——对外只暴露受控接口 | 每人单间:生活学习互不干扰 |
面向对象不只是语法,更是一种「以对象协作响应事件」的组织方式,天然适配 GUI、网络、并发等现代场景。
二、七个基本概念
| 概念 | 含义 |
|---|---|
| 对象 Object | 现实事物的抽象映射:具体属性 + 行为 |
| 类 Class | 同类事物共同特性(属性、行为)的抽象;对象的模板 |
| 属性 Field | 对象的状态/数据(成员变量) |
| 方法 Method | 对象的行为/操作 |
| 封装 Encapsulation | 数据与方法捆绑在对象内部,隐藏实现细节、只暴露受控接口 |
| 继承 Inheritance | 子类复用父类的属性与方法(extends) |
| 多态 Polymorphism | 同一接口、不同实现,运行时按实际对象分派 |
现实世界 ↔ 程序世界:
| 现实世界 | 程序世界 |
|---|---|
| 具体事物的属性及行为 | 对象 |
| 同类事物共同特性(属性、行为)的抽象 | 类 |
三、抽象:从具体到类
「抽象」不是术语,是日常思维的延伸——说「这是一把凳子」本身就是在分类。
- 方块游戏:屏幕上的每个方块有属性(位置、大小、颜色、速度)与行为(移动、旋转、碰撞),它们属于同一类「方块」,只是属性取值不同;
- 凳子:从一把具体凳子抽象出「凳子类」——属性:腿数、材质、高度;方法:承重。
贯穿示例(ERASE):游戏里棋盘是一个对象(属性:行×列的格子矩阵;行为:放置/消除方块),每个落下的方块也是对象(属性:形状、颜色、位置;行为:下落、旋转)。整个游戏就是「对象协作响应事件」——键盘事件触发方块移动,碰撞事件触发行消除。
交互实验:抽象建模器(AbstractionModeler)
从真实世界「抽象」出类:给每个候选项判定它是属性(名词)、行为(动词)还是与对象无关, 右侧类骨架代码实时生成。判错的项会标红提醒。
候选项(点选判定)
- 姓名
- 学号
- 选课(selectCourse)
- 交学费(payTuition)
- 查成绩(getGrade)
- 教室的座位号
- 今天星期几
抽象结果(实时生成)
public class Student {
}还没有判定任何候选项——先点左边的按钮试试。
关系判断:is-a(继承)还是 has-a(组合)?
「A 是一种 B」→ is-a → extends;「A 有一个 B」→ has-a → 字段引用。点选你的判断,对照参考答案。
四、案例:模拟服务大厅
把现实实体抽象为类(每类的属性与方法):
| 现实实体 | 类 | 主要属性 | 主要方法 |
|---|---|---|---|
| 顾客 | Customer | 姓名、排队号 | 取号、叫到就办理 |
| 客服 | Clerk | 工号、窗口号 | 叫号、办理业务 |
| 取号机 | TicketMachine | 当前号码 | 出票(号码 +1) |
| 号票 | Ticket | 号码、时间 | 显示号码 |
| 坐椅 | Chair | 位置 | 可坐/空着 |
| 服务大厅 | ServiceHall | 顾客列表、客服列表 | 开号、叫下一位 |
五、类的定义与对象的创建
package com.zmofun.erase.protogame; // 包:组织类、避免命名冲突、控制访问
class Dog {
String name; // 属性
int age; // 属性
Dog(String name, int age) { // 构造方法:与类同名、无返回类型,初始化对象
this.name = name;
this.age = age;
}
void bark() { // 方法
System.out.println(name + " says: woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog d = new Dog("Fido", 3); // new:堆上建对象,d 存的是引用
d.bark();
}
}
- 构造方法与类同名、无返回类型,可重载(同名不同参数);
package/import:Java 用包组织类(如 Erase 的com.zmofun.erase.protogame),import引入其他包的类。
交互实验:对象内存地图(ObjectMemoryMap)
逐步执行 Dog d = new Dog("Fido", 3);:对象在堆上,局部变量在栈上存的是引用(地址)。
栈(Stack)
堆(Heap)
点「▶ 下一步」开始执行 new。
关键区别:d 里存的不是对象本身,而是堆上对象的地址——所以「两个引用指向同一对象」是可能的。
思考题
- 用「抽象」的眼光观察你的宿舍或教室:各举 1 个「现实实体 → 类(属性 + 方法)」的例子,写出类名、2 个以上属性和 1 个以上方法。
- 仿照「模拟服务大厅」,为图书馆借书场景列出至少 4 个类(如
Book、Reader、Librarian、LoanRecord),各写主要属性与方法。 - 结合「大通铺 / 4 人间 / 单间」类比,说明面向对象的「封装」解决了面向过程的什么问题?
学习小测验
学习小测验
下列不属于面向对象核心概念的是( )
Dog d = new Dog(); 中,变量 d 里存的是( )
「模拟服务大厅」案例中,Customer 类的主要属性可能是( )
构造方法的特征是( )
package 声明的主要作用不包括( )
类与对象的关系最准确的描述是( )