面向对象封装性详解:从“加盟店”模型看公有、私有与类实例
面向对象封装性详解:从“加盟店”模型看公有、私有与类实例
文档说明:本文档基于“加盟连锁店”的生活化场景,深入剖析面向对象编程中的类属性、实例属性、公有/私有属性及方法的区别与应用。适合初学者理解封装概念。
目录
1. 核心隐喻:加盟店模型
在面向对象编程中,我们可以将复杂的概念映射到熟悉的商业场景中:
| 编程概念 | 加盟店对应物 | 解释 |
|---|---|---|
| 类 (Class) | 品牌总部 (如:蜜雪冰城) | 定义了所有门店共有的规则和特征。 |
| 实例 (Instance) | 具体门店 (如:王府井店) | 根据总部图纸建立起来的实实在在的店铺。 |
| 封装 (Encapsulation) | 店铺运营规则 | 哪些是对外公开的(菜单),哪些是内部机密(秘方)。 |
2. 属性篇:归属与权限
属性可以从两个维度来理解:“是谁的东西”(归属)和“能不能随便碰”(权限)。
2.1 第一维度:归属权(类 vs 实例)
| 概念 | 对应物 | 特征 | 代码示例 |
|---|---|---|---|
| 类属性 | 品牌名称 | 所有门店共享。总部改名,全中国都改。 | class Shop: brand = "蜜雪冰城" |
| 实例属性 | 店铺地址 | 各店独有。王府井店搬家,不影响中关村店。 | def __init__(self): self.address = "..." |
2.2 第二维度:访问权限(公有 vs 私有)
| 概念 | 对应物 | 特征 | 代码示例 |
|---|---|---|---|
| 公有属性 | 菜单价格表 | 谁都能看,甚至能改(虽然不道德)。 | self.price = 15 |
| 私有属性 | 核心秘方 | 只有店长(内部方法)能看,顾客看不见。 | self.__recipe = "机密" |
2.3 组合关系矩阵
这四个概念是两两组合的:
| 组合类型 | 归属 | 权限 | 生活例子 | 代码特征 |
|---|---|---|---|---|
| 公有类属性 | 总部 | 大家都能看 | 品牌Logo | class A: name = "..." |
| 私有类属性 | 总部 | 只有总部能看 | 年度总利润 | class A: __secret = "..." |
| 公有实例属性 | 具体门店 | 大家都能看 | 门店联系电话 | self.phone = "..." |
| 私有实例属性 | 具体门店 | 只有门店能看 | 当日流水、员工工资 | self.__profit = 0 |
3. 方法篇:谁来做主?
方法是类或实例具有的行为。根据归属不同,分为类方法和实例方法。
3.1 实例方法 (self):店长的日常
- 归属:属于具体的某一家店。
- 能力:既能动自己店里的东西(实例属性),也能用总部的招牌(类属性)。
- 场景:王府井店开业。
def open_shop(self):
print(f"位于 {self.address} 的 {self.brand} 开业啦!")
3.2 类方法 (cls):总部的红头文件
- 归属:属于整个品牌。
- 能力:只能动总部的政策(修改类属性),不知道具体门店在哪。
- 场景:总部宣布品牌升级。
@classmethod
def upgrade_brand(cls, new_name):
cls.brand_name = new_name
print(f"📢 总部通知:全品牌更名为 {cls.brand_name}!")
3.3 场景辨析:分成比例 vs 店长选举
| 业务动作 | 归属权 | 方法类型 | 操作的数据 | 现实比喻 |
|---|---|---|---|---|
| 改分成比例 | 总部 | 类方法 | 修改 类属性 |
国家调整税率,所有人都要按新税交。 |
| 选店长 | 具体店面 | 实例方法 | 修改 实例属性 |
公司选部门经理,不影响隔壁部门。 |
4. 实战演练:场景与代码
4.1 全品牌打折 vs 单店打折
- 全品牌打折:总部下达死命令(类方法修改类属性)。
- 单店打折:王府井店自己搞促销(实例方法修改实例属性)。
4.2 收款账号的封装(核心安全)
收款账号是极其敏感的信息,必须私有化。
class MilkTeaShop:
# 1. 类属性:全品牌折扣
_discount = 1.0
def init(self, name, account):
self.name = name
# 2. 私有实例属性:每个店独有的收款账号(核心机密)
self.__account = account
# 3. 实例属性:单店折扣
self.__local_discount = 1.0
===== 类方法:处理全品牌事务 =====
@classmethod
def set_nationwide_discount(cls, rate):
"""总部:全品牌打折"""
cls._discount = rate
print(f"📢 总部通知:全品牌享受{rate*10}折优惠!")
===== 实例方法:处理单店事务 =====
def set_local_discount(self, rate):
"""分店:单店打折"""
self.__local_discount = rate
print(f"🏪 {self.name}:本店限时{rate*10}折!")
def pay(self, amount):
"""公有方法:顾客付钱(唯一入口)"""
final_price = amount * self._discount * self.__local_discount
# 内部偷偷使用了私有属性 __account,外部看不到
print(f"💰 从 {self.name} 的账户 [{self.__account[-4:]}] 收款 {final_price} 元")
--- 场景演示 ---
shop1 = MilkTeaShop("王府井店", "62220202000987654321")
shop2 = MilkTeaShop("中关村店", "62284800183456789012")
1. 总部发起全品牌活动(类方法)
MilkTeaShop.set_nationwide_discount(0.8)
2. 王府井店自己搞活动(实例方法)
shop1.set_local_discount(0.95)
3. 顾客付钱(只能调用公有方法,无法直接访问账号)
shop1.pay(100)
输出:💰 从 王府井店 的账户 [4321] 收款 76.0 元
4. 尝试作恶(外部无法修改私有账号)
shop1.__account = "黑客卡号" # ❌ 报错或无效
---
## 5. 封装与安全:为什么要私有?
从设计模式角度看,私有化不仅仅是为了藏数据,更是为了实现**高内聚、低耦合**。
1. **确立“面向接口编程”**:调用者只知道 `pay(amount)`,至于背后是调用了支付宝还是微信(私有方法),完全被屏蔽。
2. **控制变化点(开闭原则)**:如果明天要把清洗逻辑换成大写,只需修改 `__clean_data` 这一个私有方法,外部的 `export` 流程和调用者完全无感。
3. **降低耦合度(迪米特法则)**:当你把 `user.password` 改为 `user.__password` 并提供 `user.verify_password(input)` 时,调用者就不再依赖 `password` 的具体存储格式。
---
## 6. 总结对照表
| 概念 | 对应实物 | 核心特征 | 代码关键词 |
| :--- | :--- | :--- | :--- |
| **类属性** | 品牌Logo | 共享:改了全改。 | 写在类里 |
| **实例属性** | 店铺地址 | 独有:各家管各家。 | `self.xxx` |
| **公有方法** | 收银台 | 对外开放,负责处理业务。 | `def method(self):` |
| **私有属性** | 保险柜里的银行卡 | 外部看不见,只能在类内部使用。 | `self.__xxx` |
| **类方法** | 总部红头文件 | 影响全局,修改类属性。 | `@classmethod` |
| **实例方法** | 店长干活 | 影响单店,修改实例属性。 | `def method(self):` |
**一句话总结:**
**公有的方法是用来“办事”的(收银),私有的属性是用来“保命”的(账号)。全品牌的事找类方法,自家的事找实例方法。**

浙公网安备 33010602011771号