# 面向對象封裝案例
## 目標
- 封裝
- 小明愛跑步
- 存放家具
### 01. 封裝
1. **封裝** 是面向對象編程的一大特點
2. 面向對象編程的 **第一步** —— 將 **屬性** 和 **方法** **封裝** 到一個抽象的 **類** 中
3. **外界** 使用 **類** 創建 **對象**,然后 **讓對象調用方法**
4. **對象方法的細節** 都被 **封裝** 在 **類的內部**
## 02. 小明愛跑步
**需求**
1. **小明** **體重** `75.0` 公斤
2. 小明每次 **跑步** 會減肥 `0.5` 公斤
3. 小明每次 **吃東西** 體重增加 `1` 公斤

> 提示:在 **對象的方法內部**,是可以 **直接訪問對象的屬性** 的!
- 代碼實現:
```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` 公斤

**提示**
1. 在 **對象的方法內部**,是可以 **直接訪問對象的屬性** 的
2. **同一個類** 創建的 **多個對象** 之間,**屬性** 互不干擾!

## 03. 擺放家具
**需求**
1. 房子(House)有戶型、 總面積和家具名稱列表
- 新房子沒有任何的家具
2. 家具(HouseItem)有名字和占地面積,其中
- **席夢思(bed)** 占地 `4` 平米
- **衣柜(chest)** 占地 `2` 平米
- **餐桌(table)** 占地 `1.5` 平米
3. 將以上三件 **家具** **添加** 到 **房子** 中
4. 打印房子時,要求輸出:**戶型**、**總面積**、**剩余面積**、**家具名稱列表**

**剩余面積**
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