利用混入类(Mixins)扩展类功能

简介: 利用混入类(Mixins)扩展类功能

问题

你有很多有用的方法,想使用它们来扩展其他类的功能。但是这些类并没有任何继承的关系。 因此你不能简单的将这些方法放入一个基类,然后被其他类继承。

解决方案

通常当你想自定义类的时候会碰上这些问题。可能是某个库提供了一些基础类, 你可以利用它们来构造你自己的类。

假设你想扩展映射对象,给它们添加日志、唯一性设置、类型检查等等功能。下面是一些混入类:

class LoggedMappingMixin:
    """
    Add logging to get/set/delete operations for debugging.
    """
    __slots__ = ()  # 混入类都没有实例变量,因为直接实例化混入类没有任何意义
    def __getitem__(self, key):
        print('Getting ' + str(key))
        return super().__getitem__(key)
    def __setitem__(self, key, value):
        print('Setting {} = {!r}'.format(key, value))
        return super().__setitem__(key, value)
    def __delitem__(self, key):
        print('Deleting ' + str(key))
        return super().__delitem__(key)
class SetOnceMappingMixin:
    '''
    Only allow a key to be set once.
    '''
    __slots__ = ()
    def __setitem__(self, key, value):
        if key in self:
            raise KeyError(str(key) + ' already set')
        return super().__setitem__(key, value)
class StringKeysMappingMixin:
    '''
    Restrict keys to strings only
    '''
    __slots__ = ()
    def __setitem__(self, key, value):
        if not isinstance(key, str):
            raise TypeError('keys must be strings')
        return super().__setitem__(key, value)

这些类单独使用起来没有任何意义,事实上如果你去实例化任何一个类,除了产生异常外没任何作用。 它们是用来通过多继承来和其他映射对象混入使用的。例如:

class LoggedDict(LoggedMappingMixin, dict):
    pass
d = LoggedDict()
d['x'] = 23
print(d['x'])
del d['x']
from collections import defaultdict
class SetOnceDefaultDict(SetOnceMappingMixin, defaultdict):
    pass
d = SetOnceDefaultDict(list)
d['x'].append(2)
d['x'].append(3)
# d['x'] = 23  # KeyError: 'x already set'

这个例子中,可以看到混入类跟其他已存在的类(比如dict、defaultdict和OrderedDict)结合起来使用,一个接一个。 结合后就能发挥正常功效了。

注意,自定义类继承的顺序很重要,父类集合中,要混入的类一定要放到前面。

相关文章
|
5月前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念,它允许我们基于现有的类(或构造函数)创建新的类
【6月更文挑战第15天】JavaScript继承促进代码复用与扩展,创建类层次结构,但过深的继承链导致复杂性增加,紧密耦合增加维护成本,单继承限制灵活性,方法覆盖可能隐藏父类功能,且可能影响性能。设计时需谨慎权衡并考虑使用组合等替代方案。
46 7
|
5月前
|
开发框架
混入mixin的原理
混入mixin的原理
|
6月前
|
JavaScript 开发者
混入Mixins:如何使用Mixins复用Vue组件逻辑
【4月更文挑战第24天】Vue.js应用的可维护性和可扩展性关键在于逻辑复用。Mixins提供了一种复用代码的高效方式,避免了组件继承导致的复杂性。Mixins是共享Vue组件选项的对象,可在多个组件间使用。创建Mixin后,通过`mixins`选项将其混入组件。当面临命名冲突时,需确保选项唯一或处理合并逻辑。Mixins还可用于条件渲染,帮助分解组件逻辑,提升代码可读性和可维护性。在开发中应根据需求灵活运用Mixins。
32 0
|
6月前
|
存储 设计模式 JavaScript
TypeScript 类的基础:从定义到实例化,让你快速掌握(三)
TypeScript 类的基础:从定义到实例化,让你快速掌握
|
6月前
|
存储 JavaScript
TypeScript 类的基础:从定义到实例化,让你快速掌握(二)
TypeScript 类的基础:从定义到实例化,让你快速掌握
|
6月前
|
缓存 JavaScript 前端开发
TypeScript 类的基础:从定义到实例化,让你快速掌握(一)
TypeScript 类的基础:从定义到实例化,让你快速掌握
|
6月前
|
存储 JavaScript 前端开发
对象和类:JS是一种基于对象的语言,可以创建和使用自定义对象。ES6引入了类的概念,使得面向对象编程更加方便。
对象和类:JS是一种基于对象的语言,可以创建和使用自定义对象。ES6引入了类的概念,使得面向对象编程更加方便。
41 0
|
算法 Python
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别(上)
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别(下)
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别(下)
|
JavaScript 前端开发
js对象的创建对象模式和继承模式(下)---继承模式
js对象的创建对象模式和继承模式(下)---继承模式
98 0