美文网首页
Python Mixin

Python Mixin

作者: kakarotto | 来源:发表于2019-01-16 12:33 被阅读0次

    我们常常在阅读一些优秀源码时,会看到有例如这种类:


    mixin.png

    什么是 mixin ?

    In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited or just reused by a subclass, while not meant for instantiation (the generation of objects of that class). Mixins are synonymous with abstract base classes. Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class or object may “inherit” most or all of its functionality from one or more mixins, therefore mixins can be thought of as a mechanism of multiple inheritance.

    Wikipedia Mixin

    简单讲,mixin 是一种类的多继承的机制。

    什么时候需要 mixin ?

    借鉴 stackoveflow 上的回答,有两个主要的使用 mixin 的场景:

    • 你希望给一个类提供很多可选的特征(feature)。
    • 你希望在很多不同的类中使用一个特定的特征(feature)。

    例如, werkzeugrequest, response系统. 我们可以实现简单request如下:

    from werkzeug import BaseRequest
    
    class Request(BaseRequest):
        pass
    

    如果希望支持accept header, 可以这样实现:

    from werkzeug import BaseRequest, AcceptMixin
    
    class Request(BaseRequest, AcceptMixin):
        pass
    

    如果希望request对象支持accept header, etags, authentication, user agent, 可以这样实现:

    from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthorizationMixin
    
    class Request(BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthorizationMixin):
        pass
    

    像C或C++这类语言都支持多重继承,一个子类可以有多个父类,这样的设计常被人诟病。
    因为继承应该是个”is-a”关系。
    比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。
    一个物品不可能是多种不同的东西,因此就不应该存在多重继承。

    不过有没有这种情况,一个类的确是需要继承多个类呢?

    答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?

    不同的语言给出了不同的方法,让我们先来看下Java。Java提供了接口interface功能,来实现多重继承:

    public abstract class Vehicle {
    }
     
    public interface Flyable {
        public void fly();
    }
     
    public class FlyableImpl implements Flyable {
        public void fly() {
            System.out.println("I am flying");
        }
    }
     
    public class Airplane extends Vehicle implements Flyable {
        private flyable;
     
        public Airplane() {
            flyable = new FlyableImpl();
        }
     
        public void fly() {
            flyable.fly();
        }
    }
    

    Python语言可没有接口功能,但是它可以多重继承。那Python是不是就该用多重继承来实现呢?是,也不是。说是,因为从语法上看,的确是通过多重继承实现的。说不是,因为它的继承依然遵守”is-a”关系,从含义上看依然遵循单继承的原则

    class Vehicle(object):
        pass
     
    class PlaneMixin(object):
        def fly(self):
            print 'I am flying'
     
    class Airplane(Vehicle, PlaneMixin):
        pass
    

    可以看到,上面的Airplane类实现了多继承,不过它继承的第二个类我们起名为PlaneMixin,而不是Plane,这个并不影响功能,但是会告诉后来读代码的人,这个类是一个Mixin类。所以从含义上理解,Airplane只是一个Vehicle,不是一个Plane。这个Mixin,表示混入(mix-in),它告诉别人,这个类是作为功能添加到子类中,而不是作为父类,它的作用同Java中的接口。

    使用Mixin类实现多重继承要非常小心 :

    • 首先它必须表示某一种功能,而不是某个物品,如同Java中的Runnable,Callable等
    • 其次它必须责任单一,如果有多个功能,那就写多个Mixin类
    • 然后,它不依赖于子类的实现
    • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了

    相关文章

      网友评论

          本文标题:Python Mixin

          本文链接:https://www.haomeiwen.com/subject/pbtmdqtx.html