• 类和对象3:组合和混入


    目录

    1. 组合的概念

    2. 组合实操:圆环计算

    3. 混入(Mixin)的概念

    4. 混入实操1:多重继承 Mixin 类

    5. 混入实操2:__dict__ 添加 Mixin 类中方法


    1. 组合的概念

    将一个类的实例对象作为属性封装在另一个类中,即类和对象的组合;

    当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好;

    组合、继承对比如下:

    • a is b 关系, 可以使用“继承”: 实现子类 a 拥有父类 b 的方法和属性;
    • a has b 关系, 可以使用“组合”: 实现一个类 a 拥有另一个类 b 的方法和属性; 

    2. 组合实操:圆环计算

    圆环由两个圆组成的,圆环面积 = 外圆面积 - 内圆面积;圆环周长 = 内圆周长 + 外圆周长。

    先实现圆形类,再组合两个圆形类实例作为圆环类的属性。

    1. #圆形类
    2. class Round:
    3. def __init__(self,radius):
    4. self.radius = radius
    5. def calculate_area(self):
    6. self.area = 3.14 * pow(self.radius,2)
    7. return self.area
    8. def calculate_perimeter(self):
    9. self.perimeter = 2 * 3.14 * self.radius
    10. return self.perimeter
    11. #圆环类
    12. class Ring:
    13. def __init__(self,round_out,round_in):
    14. self.round_out = round_out
    15. self.round_in = round_in
    16. def calculate_area(self):
    17. self.area = self.round_out.calculate_area() - self.round_in.calculate_area()
    18. return self.area
    19. def calculate_perimeter(self):
    20. self.perimeter = self.round_out.calculate_perimeter() - self.round_in.calculate_perimeter()
    21. return self.perimeter
    22. #生成两个圆形类的实例对象,作为圆环类实例对象的封装属性
    23. round1 = Round(10)
    24. round2 = Round(7.5)
    25. ring0 = Ring(round1,round2)
    26. #执行运算成功
    27. ring0.calculate_area()
    28. 137.375
    29. ring0.calculate_perimeter()
    30. 15.700000000000003

    3. 混入(Mixin)的概念

    混入(Mixin 或 mix-in) 和组合一样,本身不是代码逻辑或方法,而是一种设计模式,常在面向对象编程中应用;

    Mixin 的设计思想可以理解为,将程序中需要经常共享的功能细分成一个个 Mixin 类,Mixin 类通常具有如下特定:

    • Mixin 类中包含其他类所需要的功能,但通常不直接实例化,而是作为供其他类使用的一个个“功能模块”;
    • Mixin 类通常功能单一,方便不同类简单复用,如果需要多个功能,那就写多个Mixin类;
    • Mixin 类通常不依赖其他类,拒绝复杂的继承关系,避免出现多重继承陷阱。

    实际编程中,通常在定义 Mixin 类时,在其名字后添加 Mixin 后缀,如:class FunctionMixin: ,但这些都不是强制要求,对于 Python 而言,也没有特殊的效果。

    可以将 Mixin 类理解为功能更齐全的,更方便面向对象编程的“函数”,Python3.X 以上版本中,通常可以使用多重继承或 __dict__ 添加方法的形式,应用 Mixin 类。

    4. 混入实操1:多重继承 Mixin 类

    Python 支持多重继承,参见类和对象2:集成,通过定义一个新的子类,多重继承多个 Mixin 类:

    1. #两个 Mixin 类
    2. class FunAMixin:
    3. def funa_plus(self,a,b):
    4. print(f'{a} + {b} = {a+b}')
    5. class FunBMixin:
    6. def funb_reduce(self,a,b):
    7. print(f'{a} - {b} = {a - b}')
    8. #创建一个多重继承多个 Mixin 类的子类
    9. class Calculate1(FunAMixin,FunBMixin):
    10. pass
    11. #调用 Mixin 类功能正常
    12. ctest = Calculate1()
    13. ctest.funa_plus(1,2)
    14. 1 + 2 = 3
    15. ctest.funb_reduce(1,2)
    16. 1 - 2 = -1

    5. 混入实操2:__dict__ 添加 Mixin 类中方法

    有时当需求发生变化需要新的功能,但直接修改类可能导致许多风险,此时我们可以创建一个类的实例对象,再通过 Mixin 类将新的方法导入到实例对象的 __dict__ 属性中,;

    实例对象的 __dict__ 属性,是一个用于存储对象(可写)属性的字典,存储着类的各类方法和变量;

    如下实例中,通过 Plug 父类,及其 Mixin 子类,将新的方法以“插件”的形式,“插入”或“移除”实例对象中:

    1. #插件父类
    2. class Plug:
    3. def __init__(self):
    4. self.expandfunc_list = []
    5. def plugin(self, newobject):
    6. for func in self.expandfunc_list:
    7. newobject.__dict__[func.__name__] = func
    8. def plugout(self, newobject):
    9. for func in self.expandfunc_list:
    10. del newobject.__dict__[func.__name__]
    11. #基于插件父类创建 Mixin 子类,可直接在实例对象中增删新的方法
    12. class FunAMixin(Plug):
    13. def __init__(self):
    14. super().__init__()
    15. self.expandfunc_list.append(self.funa_plus)
    16. def funa_plus(self, a, b):
    17. print(f'{a} + {b} = {a + b}')
    18. class FunBMixin(Plug):
    19. def __init__(self):
    20. super().__init__()
    21. self.expandfunc_list.append(self.funb_reduce)
    22. def funb_reduce(self, a, b):
    23. print(f'{a} - {b} = {a - b}')
    24. #创建测试用的类和实例对象
    25. class Test:
    26. pass
    27. testobject = Test()
    28. #将 Mixin 类中的方法增加到实例对象中
    29. FunAMixin().plugin(testobject)
    30. FunBMixin().plugin(testobject)
    31. #实例对象调用新增加的方法,正常执行
    32. testobject.funa_plus(5,1)
    33. 5 + 1 = 6
    34. testobject.funb_reduce(5,1)
    35. 5 - 1 = 4
    36. #将 Mixin 类中的方法从实例对象中删除
    37. FunBMixin().plugout(testobject)
    38. #实例对象调用已删除的方法,无法执行
    39. testobject.funb_reduce(5,1)
    40. Traceback (most recent call last):
    41. File "<input>", line 1, in <module>
    42. AttributeError: 'Test' object has no attribute 'funb_reduce'

  • 相关阅读:
    基于Python、wxpython的高校教务系统设计与实现
    配置定时任务的 cron 表达式有哪几种?
    跨站请求伪造(CSRF)攻击与防御原理
    ICCV2023 Tracking paper汇总(二)(多目标跟随、单目标跟随等)
    SpringBoot 全局事务配置
    【深度学习】数据集最常见的问题及其解决方案
    STM32CubeMX外部中断
    C++类型转换+特殊类的设计+单例模式+IO流+空间配置器
    Java设计模式:fly weight 享元模式
    Java直接量(字面量)
  • 原文地址:https://blog.csdn.net/davidksatan/article/details/125477578