#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
=====================================
Python 面向对象编程:多重继承完全指南
=====================================

本文件系统介绍 Python OOP 核心特性:
1. 类(Class) 与 实例(Instance) —— 基础封装
2. 单继承(Single Inheritance) —— 代码复用
3. 多重继承(Multiple Inheritance) —— 复杂继承关系
4. super() 函数 —— MRO (方法解析顺序) 与协同初始化
5. **kwargs 模式 —— 灵活的参数传递链

【场景设定】
  学校中存在以下角色关系:

        Person (人) ─── 基类,所有人都有姓名,都会说话
        ├── Student (学生) ─── 有年级属性,会学习
        ├── Teacher (教师) ─── 有学科属性,会教书
        └── TeachingAssistant (助教) ─── 既是学生又是教师!
           (多重继承: 同时拥有学生和教师的特征)

作者:bloxed
日期:2026-05-18
"""


# ============================================================
# 第一部分:基类定义 —— Person
# ============================================================
class Person:
    """
    人类基类 (Base Class / Parent Class)
    
    [★核心概念]
      - 基类: 被其他类继承的类,提供通用属性和方法
      - 封装: 将数据(name)和行为(speak)绑定在一起
      - self: 代表实例本身,通过 self 访问实例属性和方法
    """
    
    def __init__(self, name, **kwargs):
        """
        构造函数:创建实例时自动调用
        
        参数:
            name: 姓名 (必需参数)
            **kwargs: 关键字参数收集器 (★关键设计!)
                     用于将未处理的参数传递给父类的 __init__
                     
        [★为什么用 **kwargs?]
          在多重继承链中,每个类可能需要不同的初始化参数。
          通过 **kwargs 收集多余参数并传递给 super().__init__(),
          可以确保继承链上每个父类都能拿到自己需要的参数。
          
          这就是 "协作式多重继承" (Cooperative Multiple Inheritance) 的标准模式!
        """
        self.name = name  # 实例属性: 每个实例有自己独立的 name

    def speak(self):
        """基类通用方法: 所有人都能说话"""
        return f"{self.name}: 你好!"


# ============================================================
# 第二部分:单继承 —— Student
# ============================================================
class Student(Person):
    """
    学生类 (Single Inheritance from Person)
    
    继承关系: Student → Person
    Student 自动拥有 Person 的所有属性和方法,
    同时扩展了自己特有的属性 (grade) 和方法 (study)
    
    [★继承的优势]
      1. 代码复用: 不需要重新定义 name 和 speak()
      2. 层次清晰: 表达"is-a"关系 (Student IS-A Person)
      3. 易于维护: 修改 Person.speak() 时所有子类自动生效
    """
    
    def __init__(self, name, grade, **kwargs):
        """
        学生构造函数
        
        参数:
            name:  姓名 (传递给 Person.__init__)
            grade: 年级 (Student 特有属性)
            **kwargs: 传递给 super().__init__() 的额外参数
            
        [★super().__init__() 的作用]
          调用父类 Person 的构造函数,完成 name 的初始化。
          这确保了即使将来 Person 的初始化逻辑发生变化,
          子类也不需要修改代码。
        """
        super().__init__(name=name, **kwargs)  # ★ 调用父类构造器,传递 name 和剩余 kwargs
        self.grade = grade  # Student 特有属性

    def study(self):
        """Student 特有方法: 描述学习行为"""
        return f"{self.name} (Grade {self.grade}) 正在学习."


# ============================================================
# 第三部分:单继承 —— Teacher
# ============================================================
class Teacher(Person):
    """
    教师类 (Single Inheritance from Person)
    
    继承关系: Teacher → Person
    与 Student 平级,都是 Person 的子类
    """
    
    def __init__(self, name, subject, **kwargs):
        """
        教师构造函数
        
        参数:
            name:    姓名 (传递给 Person)
            subject: 任教科目 (Teacher 特有属性)
            **kwargs: 额外参数传递给父类
        """
        super().__init__(name=name, **kwargs)  # ★ 同样使用 super() 协作模式
        self.subject = subject  # Teacher 特有属性

    def teach(self):
        """Teacher 特有方法: 描述教学行为"""
        return f"{self.name} 正在教授 {self.subject} 课程."


# ============================================================
# 第四部分:多重继承 —— TeachingAssistant ⭐⭐⭐
# ============================================================
class TeachingAssistant(Student, Teacher):
    """
    助教类 (Multiple Inheritance) ★★★ 核心重点 ★★★
    
    继承关系: TeachingAssistant → Student → Person
                              └── Teacher ──┘
    
    [★什么是多重继承?]
      一个类同时继承多个父类,同时获得所有父类的属性和方法。
      这里 TeachingAssistant 同时继承了 Student 和 Teacher。
      
    [★MRO (Method Resolution Order) 方法解析顺序]
      Python 使用 C3 算法确定方法查找顺序:
      
        TeachingAssistant.mro() = 
        [TeachingAssistant, Student, Teacher, Person, object]
      
      查找方法时按此顺序: 先找自身 → 再找 Student → 再找 Teacher → ...
      
      如果多个父类有同名方法,排在前面的优先!
      
    [!潜在问题: 菱形继承 Diamond Problem]
                Person
               /      \
           Student   Teacher
               \      /
          TeachingAssistant
      
      TeachingAssistant 通过两条路径继承了 Person。
      Python 的 MRO 确保 Person.__init__() 只被调用一次,
      这正是 super() 协作模式的威力所在!
    """
    
    def __init__(self, name, grade, subject):
        """
        助教构造函数 —— 多重继承的初始化协调
        
        参数:
            name:    姓名 → 传给 Person (最终)
            grade:   年级 → Student 需要
            subject: 科目 → Teacher 需要
        
        [★super() 在多重继承中的魔法]
          当 TeachingAssistant 调用 super().__init__(name=name, grade=grade, subject=subject):
          
          1. MRO 找到下一个类: Student
          2. Student.__init__ 接收 name 和 grade,调用 super()
          3. MRO 继续: 下一个是 Teacher
          4. Teacher.__init__ 接收 name 和 subject,调用 super()
          5. MRO 继续: 最后是 Person
          6. Person.__init__ 接收 name,完成初始化
          
          整条链路自动串联! 这就是协作式继承的核心。
        """
        # [★] 使用关键字参数形式,让每个父类各取所需
        super().__init__(name=name, grade=grade, subject=subject)

    def assist(self):
        """
        TeachingAssistant 特有方法
        结合了 Student 和 Teacher 双重身份的特征
        """
        return (f"{self.name}{self.grade} 年级的助教,"
                f"同时协助教授 {self.subject} 课程。")


# ============================================================
# 第五部分:运行演示 —— 验证继承体系
# ============================================================
print("=" * 60)
print("  Python 多重继承演示")
print("=" * 60)


# --- 创建助教实例 ---
print("\n【创建实例】")
ta = TeachingAssistant("Alice", "10th", "Mathematics")
print(f"  实例类型: {type(ta).__name__}")
print(f"  继承链 (MRO):")
for idx, cls in enumerate(ta.__class__.__mro__):
    print(f"    [{idx}] {cls.__name__}")


# --- 方法调用测试 ---
print("\n【继承的方法调用】")

# 从 Person 继承的 speak()
print(f"\n  1. speak()  [来自 Person]:")
print(f"     → {ta.speak()}")

# 从 Student 继承的 study()
print(f"\n  2. study()  [来自 Student]:")
print(f"     → {ta.study()}")

# 从 Teacher 继承的 teach()
print(f"\n  3. teach()  [来自 Teacher]:")
print(f"     → {ta.teach()}")

# TeachingAssistant 自身的 assist()
print(f"\n  4. assist() [来自 TeachingAssistant 自身]:")
print(f"     → {ta.assist()}")


# --- isinstance / issubclass 验证 ---
print("\n【类型检查 (isinstance / issubclass)】")
print(f"  isinstance(ta, TeachingAssistant): {isinstance(ta, TeachingAssistant)}")
print(f"  isinstance(ta, Student):           {isinstance(ta, Student)}")
print(f"  isinstance(ta, Teacher):           {isinstance(ta, Teacher)}")
print(f"  isinstance(ta, Person):            {isinstance(ta, Person)}")
print(f"  issubclass(TeachingAssistant, Person): {issubclass(TeachingAssistant, Person)}")


# --- 属性访问验证 ---
print("\n【属性访问验证】")
print(f"  ta.name    (Person):     '{ta.name}'")
print(f"  ta.grade   (Student):    '{ta.grade}'")
print(f"  ta.subject (Teacher):    '{ta.subject}'")


# --- 对比: 单独创建 Student 和 Teacher ---
print("\n【对比: 单独的 Student 和 Teacher 实例】")

student_only = Student("Bob", "11th")
teacher_only = Teacher("Charlie", "Physics")

print(f"\n  Student Bob:")
print(f"    speak():  {student_only.speak()}")
print(f"    study():  {student_only.study()}")
print(f"    has 'teach'? {'teach' in dir(student_only)}")  # False

print(f"\n  Teacher Charlie:")
print(f"    speak():  {teacher_only.speak()}")
print(f"    teach():  {teacher_only.teach()}")
print(f"    has 'study'? {'study' in dir(teacher_only)}")  # False

print(f"\n  TA Alice (兼具两者):")
print(f"    has 'study'?  {'study' in dir(ta)}")    # True (from Student)
print(f"    has 'teach'?  {'teach' in dir(ta)}")    # True (from Teacher)
print(f"    has 'assist'? {'assist' in dir(ta)}")    # True (own method)


# ============================================================
# 第六部分:总结 —— 多重继承要点
# ============================================================
print("\n" + "=" * 60)
print("  多重继承核心要点总结")
print("=" * 60)
summary = r"""
+------------------------------------------------------------+
|  [Inheritance Type Comparison]                             |
|                                                            |
|    Single:   class A(B)           -- One parent, simple     |
|    Multiple: class A(B, C)       -- Multi-parent, combo    |
|                                                            |
|  [MRO - Method Resolution Order]                           |
|                                                            |
|    Python 3 uses C3 Linearization algorithm                |
|    View: ClassName.mro() or ClassName.__mro__              |
|    Rule: Child > Left-Parent > Right-Parent > Ancestor     |
|                                                            |
|  [super() Best Practices]                                  |
|                                                            |
|    YES: Always use super().__init__(**kwargs)              |
|    YES: Subclass takes own args + **kwargs                 |
|    YES: Parents pick what they need from kwargs            |
|    NO:  Don't hardcode: Person.__init__(self, name)        |
|                                                            |
|  [When to Use Multiple Inheritance?]                       |
|                                                            |
|    Good: Mixin pattern, Interface composition, Roles        |
|    Careful: Can greatly increase code complexity           |
|    Alternative: Favor Composition over Inheritance         |
|                                                            |
|  [Built-in Functions for Introspection]                    |
|                                                            |
|    isinstance(obj, Class)   -- Is obj an instance?         |
|    issubclass(A, B)         -- Is A a subclass of B?       |
|    type(obj)                -- Exact type of object        |
|    obj.__class__.__mro__   -- Full MRO chain               |
+------------------------------------------------------------+
"""
print(summary)

print("\n程序运行完毕!")

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐