# 面向对象封装案例
## 目标
- 封装
- 小明爱跑步
- 存放家具
### 01. 封装
1. **封装** 是面向对象编程的一大特点
2. 面向对象编程的 **第一步** —— 将 **属性** 和 **方法** **封装** 到一个抽象的 **类** 中
3. **外界** 使用 **类** 创建 **对象**,然后 **让对象调用方法**
4. **对象方法的细节** 都被 **封装** 在 **类的内部**
## 02. 小明爱跑步
**需求**
1. **小明** **体重** `75.0` 公斤
2. 小明每次 **跑步** 会减肥 `0.5` 公斤
3. 小明每次 **吃东西** 体重增加 `1` 公斤
![](https://pic.downk.cc/item/5e884513504f4bcb04adaa1e.jpg)
> 提示:在 **对象的方法内部**,是可以 **直接访问对象的属性** 的!
- 代码实现:
```python
class Person:
"""人类"""
def __init__(self, name, weight):
self.name = name
self.weight = weight
def __str__(self):
return "我的名字叫 %s 体重 %.2f 公斤" % (self.name, self.weight)
def run(self):
"""跑步"""
print("%s 爱跑步,跑步锻炼身体" % self.name)
self.weight -= 0.5
def eat(self):
"""吃东西"""
print("%s 是吃货,吃完这顿再减肥" % self.name)
self.weight += 1
xiaoming = Person("小明", 75)
xiaoming.run()
xiaoming.eat()
xiaoming.eat()
print(xiaoming)
```
### 2.1 小明爱跑步扩展 —— 小美也爱跑步
**需求**
1. **小明** 和 **小美** 都爱跑步
2. **小明** **体重** `75.0` 公斤
3. **小美** **体重** `45.0` 公斤
4. 每次 **跑步** 都会减少 `0.5` 公斤
5. 每次 **吃东西** 都会增加 `1` 公斤
![](https://pic.downk.cc/item/5e884513504f4bcb04adaa1e.jpg)
**提示**
1. 在 **对象的方法内部**,是可以 **直接访问对象的属性** 的
2. **同一个类** 创建的 **多个对象** 之间,**属性** 互不干扰!
![](https://pic.downk.cc/item/5e85cc1c504f4bcb042f453b.jpg)
## 03. 摆放家具
**需求**
1. 房子(House)有户型、 总面积和家具名称列表
- 新房子没有任何的家具
2. 家具(HouseItem)有名字和占地面积,其中
- **席梦思(bed)** 占地 `4` 平米
- **衣柜(chest)** 占地 `2` 平米
- **餐桌(table)** 占地 `1.5` 平米
3. 将以上三件 **家具** **添加** 到 **房子** 中
4. 打印房子时,要求输出:**户型**、**总面积**、**剩余面积**、**家具名称列表**
![](https://pic.downk.cc/item/5e8845b1504f4bcb04ae7c12.jpg)
**剩余面积**
1. 在创建房子对象时,定义一个 **剩余面积的属性**,**初始值和总面积相等**
2. 当调用 `add_item` 方法,向房间 **添加家具** 时,让 **剩余面积** -= **家具面积**
**思考**:应该先开发哪一个类?
**答案** —— **家具类**
1. 家具简单
2. 房子要使用到家具,**被使用的类**,通常应该先开发
### 3.1 创建家具
```python
class HouseItem:
def __init__(self, name, area):
"""
:param name: 家具名称
:param area: 占地面积
"""
self.name = name
self.area = area
def __str__(self):
return "[%s] 占地面积 %.2f" % (self.name, self.area)
# 1. 创建家具
bed = HouseItem("席梦思", 4)
chest = HouseItem("衣柜", 2)
table = HouseItem("餐桌", 1.5)
print(bed)
print(chest)
print(table)
```
**小结**
1. 创建了一个 **家具类**,使用到 `__init__` 和 `__str__` 两个内置方法
2. 使用 **家具类** 创建了 **三个家具对象**,并且 **输出家具信息**
### 3.2 创建房间
```python
class House:
def __init__(self, house_type, area):
"""
:param house_type: 户型
:param area: 总面积
"""
self.house_type = house_type
self.area = area
# 剩余面积默认和总面积一致
self.free_area = area
# 默认没有任何的家具
self.item_list = []
def __str__(self):
# Python 能够自动的将一对括号内部的代码连接在一起
return ("户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s"
% (self.house_type, self.area,
self.free_area, self.item_list))
def add_item(self, item):
print("要添加 %s" % item)
...
# 2. 创建房子对象
my_home = House("两室一厅", 60)
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)
```
**小结**
1. 创建了一个 **房子类**,使用到 `__init__` 和 `__str__` 两个内置方法
2. 准备了一个 `add_item` 方法 **准备添加家具**
3. 使用 **房子类** 创建了 **一个房子对象**
4. 让 **房子对象** 调用了三次 `add_item` 方法,将 **三件家具** 以实参传递到 `add_item` 内部
### 3.3 添加家具
**需求**
- **判断** **家具的面积** 是否 **超过剩余面积**,**如果超过**,提示不能添加这件家具
- 将 **家具的名称** 追加到 **家具名称列表** 中
- 用 **房子的剩余面积** - **家具面积**
```python
def add_item(self, item):
print("要添加 %s" % item)
# 1. 判断家具面积是否大于剩余面积
if item.area > self.free_area:
print("%s 的面积太大,不能添加到房子中" % item.name)
return
# 2. 将家具的名称追加到名称列表中
self.item_list.append(item.name)
# 3. 计算剩余面积
self.free_area -= item.area
```
### 3.4 小结
- 主程序只负责创建 **房子** 对象和 **家具** 对象
- 让 **房子** 对象调用 `add_item` 方法 **将家具添加到房子**中
- **面积计算**、**剩余面积**、**家具列表** 等处理都被 **封装** 到 **房子类的内部**
- linux基础
- 01_Python基础课程安排
- 02_操作系统(科普章节)
- 03_操作系统的发展史(科普章节)
- 04_文件和目录(理解)
- 05_Ubuntu图形界面入门
- 06_常用Linux命令的基本使用
- 07_Linux终端命令格式
- 08_文件和目录常用命令
- 09_远程管理常用命令
- 10_用户权限相关命令
- 11_系统信息相关命令
- 12_其他命令
- python基础
- 01_认识 Python
- 02_第一个Python 程序
- 03_PyCharm的初始设置(知道)
- 04_多文件项目的演练
- 05_注释
- 06_算数运算符
- 07_程序执行原理(科普)
- 08_变量的基本使用
- 09_变量的命名
- 10_判断(if)语句
- 11_运算符
- 12_循环
- 13_函数基础
- 14_高级变量类型
- 15_综合应用——名片管理系统
- 16_变量进阶(理解)
- 17_函数进阶.md
- 面向对象
- 01_面向对象(OOP)基本概念
- 02_类和对象
- 03_面向对象基础语法
- 04_面向对象封装案例
- 05_面向对象封装案例 II