程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

    • 环境搭建
    • 标识符
    • 变量
    • 缩进和注释
    • 数据类型
    • 数据类型转换
    • 运算符
    • 字符串
    • 列表
    • 元组
    • 字典
    • 集合
    • if判断
    • for循环
    • while循环
    • 循环综合练习
    • Python函数
    • 函数与循环实战
    • 生成式
    • 文件读写
    • 面向对象
    • 面向对象综合案例
      • 1. 案例一:银行账户系统——封装与数据验证
        • 1.1 需求分析
        • 1.2 设计思路
        • 1.3 代码实现与讲解
      • 2. 案例二:图书馆系统——类之间的协作
        • 2.1 需求分析
        • 2.2 设计思路
        • 2.3 代码实现与讲解
      • 3. 案例三:员工管理系统——继承与多态
        • 3.1 需求分析
        • 3.2 设计思路
        • 3.3 代码实现与讲解
      • 4. 总结
  • Python 进阶

  • Python
  • Python 基础
scholar
2025-07-20
目录

面向对象综合案例

# 面向对象实战案例


面向对象编程 (OOP) 不仅仅是语法,更是一种强大的编程思想。通过将现实世界中的概念抽象为代码中的“对象”,我们可以构建出结构清晰、易于维护和扩展的复杂系统。

# 1. 案例一:银行账户系统——封装与数据验证

这个案例将重点展示如何通过 封装 保护数据安全,并利用 @property 装饰器实现优雅的数据验证。

# 1.1 需求分析

  • 创建一个 BankAccount 类,管理用户的银行账户。
  • 属性: 账户名 (owner)、余额 (balance)、账户类型 (account_type)。
  • 行为:
    • 开户: 创建账户时,必须提供户主名和初始余额。
    • 存款 (deposit): 存入金额必须为正数。
    • 取款 (withdraw): 取款金额必须为正数,且不能超过当前余额。
    • 查询信息 (display_info): 显示账户的详细信息。
  • 约束: 余额不能被外部直接修改,必须通过存款和取款方法进行。

# 1.2 设计思路

  • 封装余额: 将余额属性 _balance 设为内部属性(以 _ 开头),防止外部直接访问。
  • @property 装饰器: 创建一个名为 balance 的只读属性,外部只能通过它来安全地“读取” _balance 的值。
  • 方法设计:
    • __init__: 初始化所有属性,并对初始余额进行验证。
    • deposit 和 withdraw: 实现核心业务逻辑,并在方法内部修改 _balance。
    • display_info: 格式化输出账户信息。

# 1.3 代码实现与讲解

class BankAccount:
    """
    一个代表银行账户的类。
    这个类通过封装和属性验证来确保账户操作的安全性。
    """
    def __init__(self, owner, initial_balance=0.0):
        # 公开属性:账户所有者姓名
        self.owner = owner
        
        # 内部属性:账户余额,以单下划线开头表示不建议外部直接访问
        # 我们将通过 getter 和 setter 来控制它
        if initial_balance < 0:
            raise ValueError("初始余额不能为负数!")
        self._balance = float(initial_balance)

    @property
    def balance(self):
        """
        余额的 getter。
        使用 @property 装饰器,让我们可以像访问属性一样调用这个方法(例如 account.balance)。
        这是一个只读属性,外部无法通过 account.balance = XXX 来修改。
        """
        return self._balance

    def deposit(self, amount):
        """
        存款方法。
        """
        # 验证存款金额
        if amount > 0:
            self._balance += float(amount)
            print(f"✅ 存款成功:{amount:.2f} 元。")
            self.display_info()
        else:
            print("❌ 存款失败:金额必须为正数。")

    def withdraw(self, amount):
        """
        取款方法。
        """
        # 验证取款金额
        if amount <= 0:
            print("❌ 取款失败:金额必须为正数。")
        # 验证余额是否充足
        elif amount > self._balance:
            print(f"❌ 取款失败:余额不足。当前余额 {self.balance:.2f} 元,尝试取款 {amount:.2f} 元。")
        else:
            self._balance -= float(amount)
            print(f"✅ 取款成功:{amount:.2f} 元。")
            self.display_info()

    def display_info(self):
        """
        显示当前账户信息。
        """
        print(f"--- 账户信息 ---\n户主: {self.owner}\n余额: {self.balance:.2f} 元\n---------------")

# --- 代码测试 ---
print("--- 创建账户 ---")
my_account = BankAccount("张三", 1000.0)
my_account.display_info()

print("\n--- 存取款操作 ---")
my_account.deposit(500.50)
my_account.withdraw(200)
my_account.withdraw(1500) # 尝试超额取款
my_account.deposit(-100)  # 尝试存入负数

# 尝试直接修改余额(会失败,因为 balance 是只读属性)
try:
    my_account.balance = 5000
except AttributeError as e:
    print(f"\n❌ 直接修改余额失败: {e}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

# 2. 案例二:图书馆系统——类之间的协作

这个案例将重点展示如何设计多个类 (Book 和 Library),并让它们相互协作,共同完成一个更复杂的任务。

# 2.1 需求分析

  • Book 类: 存储单本书籍的信息,包括书名 (title)、作者 (author) 和 ISBN 编号 (isbn)。
  • Library 类: 代表整个图书馆,需要管理多本书籍。
  • 功能:
    • 入库 (add_book): 将一本新书(一个 Book 对象)添加到图书馆。
    • 借阅 (borrow_book): 根据 ISBN 借出一本书,并记录其为“已借出”状态。
    • 归还 (return_book): 根据 ISBN 归还一本书,并记录其为“可用”状态。
    • 查询 (find_book): 根据 ISBN 查找书籍信息。
    • 展示 (display_all_books): 显示图书馆所有藏书及其状态。

# 2.2 设计思路

  • Book 类: 一个简单的数据类。为其添加 __str__ 方法可以方便地打印书籍信息。
  • Library 类:
    • 使用一个字典 _books 来存储所有 Book 对象,键为 ISBN,值为 Book 对象。这使得通过 ISBN 查找书籍非常高效。
    • 使用一个集合 _borrowed_isbns 来专门记录已借出书籍的 ISBN。集合的查找、添加和删除操作效率很高。
  • 协作: Library 类的方法会接收、存储和操作 Book 类的实例,体现了类之间的协作关系。

# 2.3 代码实现与讲解

class Book:
    """代表一本书的数据类。"""
    def __init__(self, title, author, isbn):
        self.title = title
        self.author = author
        self.isbn = isbn # ISBN 作为书籍的唯一标识

    def __str__(self):
        """
        定义对象的字符串表示形式。
        当我们 print(一个Book对象) 时,会自动调用这个方法。
        """
        return f"《{self.title}》 by {self.author} (ISBN: {self.isbn})"

class Library:
    """代表图书馆的类,管理书籍的借阅。"""
    def __init__(self, name):
        self.name = name
        # 内部属性:使用字典存储所有书籍,ISBN为键,Book对象为值
        self._books = {}
        # 内部属性:使用集合存储已借出书籍的ISBN,查询效率高
        self._borrowed_isbns = set()

    def add_book(self, book):
        """将一本书(Book对象)添加入库。"""
        if isinstance(book, Book):
            if book.isbn not in self._books:
                self._books[book.isbn] = book
                print(f"✅ 入库成功: {book}")
            else:
                print(f"🟡 信息: ISBN {book.isbn} 已存在,无需重复入库。")
        else:
            print("❌ 错误: 只能添加入库 Book 类型的对象。")

    def borrow_book(self, isbn):
        """根据 ISBN 借书。"""
        # 检查书籍是否存在
        if isbn not in self._books:
            print(f"❌ 借阅失败: ISBN {isbn} 不存在。")
        # 检查书籍是否已被借出
        elif isbn in self._borrowed_isbns:
            print(f"🟡 借阅失败: 《{self._books[isbn].title}》已被借出。")
        # 执行借阅
        else:
            self._borrowed_isbns.add(isbn)
            print(f"✅ 借阅成功: 《{self._books[isbn].title}》。")

    def return_book(self, isbn):
        """根据 ISBN 还书。"""
        if isbn not in self._books:
            print(f"❌ 归还失败: ISBN {isbn} 不属于本馆。")
        elif isbn in self._borrowed_isbns:
            self._borrowed_isbns.remove(isbn)
            print(f"✅ 归还成功: 《{self._books[isbn].title}》。")
        else:
            print(f"🟡 信息: 《{self._books[isbn].title}》未被借出,无需归还。")

    def display_all_books(self):
        """显示所有馆藏书籍及其状态。"""
        print(f"\n--- {self.name} 藏书清单 ---")
        if not self._books:
            print("图书馆暂无藏书。")
            return
        
        for isbn, book in self._books.items():
            status = "已借出" if isbn in self._borrowed_isbns else "在馆"
            print(f"- {book} [状态: {status}]")
        print("------------------------")

# --- 代码测试 ---
# 创建书籍对象
book1 = Book("Python编程:从入门到实践", "Eric Matthes", "978-7-115-42802-8")
book2 = Book("流畅的Python", "Luciano Ramalho", "978-7-115-45417-1")
book3 = Book("算法导论", "Thomas H. Cormen", "978-7-111-40701-0")

# 创建图书馆并入库书籍
my_library = Library("城市图书馆")
my_library.add_book(book1)
my_library.add_book(book2)
my_library.add_book(book3)
my_library.display_all_books()

# 借阅与归还
print("\n--- 借阅与归还操作 ---")
my_library.borrow_book("978-7-115-45417-1")
my_library.borrow_book("978-7-115-45417-1") # 重复借阅
my_library.return_book("978-7-115-45417-1")
my_library.borrow_book("999-9-999-99999-9") # 借阅不存在的书

my_library.display_all_books()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

# 3. 案例三:员工管理系统——继承与多态

这个案例将重点展示如何使用 继承 来构建类层次结构,并利用 多态 编写出更具扩展性的通用代码。

# 3.1 需求分析

  • 基类 Employee: 包含所有员工共有的属性,如姓名 (name) 和月薪 (salary)。以及一个计算年薪 get_annual_salary 的方法。
  • 子类 Manager: 继承 Employee,并有自己独特的属性——绩效奖金 (bonus)。其年薪计算方式为:月薪 * 12 + 绩效奖金。
  • 子类 Developer: 继承 Employee,并有自己独特的属性——项目分红 (dividend)。其年薪计算方式为:月薪 * 12 + 项目分红。
  • 功能:
    • 创建不同类型的员工(经理、开发者)。
    • 能够统一计算并打印所有员工的年薪,无论其具体职位是什么。

# 3.2 设计思路

  • 继承: Manager 和 Developer 都从 Employee 继承。它们自动获得了 name 和 salary 属性,以及 __init__ 方法。通过 super().__init__() 调用父类的构造方法来初始化通用属性。
  • 方法重写: Manager 和 Developer 都需要重写 get_annual_salary 方法,以实现各自独特的年薪计算逻辑。
  • 多态: 创建一个统一的函数,该函数接收一个员工列表(其中可以包含 Manager 和 Developer 对象)。遍历列表,对每个员工对象调用 get_annual_salary 方法。Python 会自动根据对象的实际类型(是 Manager 还是 Developer)来调用正确的重写方法。这就是多态。

# 3.3 代码实现与讲解

class Employee:
    """员工基类。"""
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def get_annual_salary(self):
        """计算基础年薪。"""
        return self.salary * 12
        
    def display_info(self):
        """显示员工基本信息。"""
        print(f"姓名: {self.name}, 职位: {self.__class__.__name__}, 年薪: {self.get_annual_salary()} 元")

class Manager(Employee):
    """经理子类。"""
    def __init__(self, name, salary, bonus):
        # 调用父类的 __init__ 方法来初始化 name 和 salary
        super().__init__(name, salary)
        # 初始化子类特有的属性
        self.bonus = bonus

    def get_annual_salary(self):
        """
        重写父类的方法,以实现新的年薪计算逻辑。
        先通过 super() 获取父类的计算结果,再加上自己的奖金。
        """
        base_annual_salary = super().get_annual_salary()
        return base_annual_salary + self.bonus

class Developer(Employee):
    """开发者子类。"""
    def __init__(self, name, salary, dividend):
        super().__init__(name, salary)
        self.dividend = dividend

    def get_annual_salary(self):
        """重写父类的方法。"""
        base_annual_salary = super().get_annual_salary()
        return base_annual_salary + self.dividend

# --- 多态演示 ---
def print_all_employee_info(employees):
    """
    这个函数接收一个包含不同员工对象的列表。
    它不关心每个员工的具体类型,只管调用它们的 display_info 方法。
    Python 会自动根据对象的实际类型执行相应的方法,这就是多态。
    """
    print("\n--- 公司年度薪酬报表 ---")
    for employee in employees:
        employee.display_info()
    print("------------------------")

# --- 代码测试 ---
# 创建不同类型的员工对象
manager1 = Manager("王经理", 20000, 50000)
dev1 = Developer("小张", 15000, 30000)
dev2 = Developer("小李", 16000, 35000)

# 将所有员工放入同一个列表
employee_list = [manager1, dev1, dev2]

# 调用多态函数,统一处理
print_all_employee_info(employee_list)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# 4. 总结

通过以上三个案例,我们实践了面向对象的三大核心支柱:

  1. 封装 (案例一): 我们将 _balance 隐藏起来,只通过 deposit 和 withdraw 方法来修改它,保证了数据的安全性和一致性。
  2. 协作 (案例二): 我们设计了 Book 和 Library 两个独立的类,它们各司其职,并通过对象间的交互共同实现了一个完整的图书馆系统。
  3. 继承与多态 (案例三): 我们通过 Employee 基类实现了代码的重用,并通过 Manager 和 Developer 子类扩展了功能。最后,利用多态性,我们编写了可以统一处理不同类型对象的通用代码,大大增强了程序的灵活性和可扩展性。
编辑此页 (opens new window)
上次更新: 2025/07/23, 06:33:16
面向对象
装饰器与生成器

← 面向对象 装饰器与生成器→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式