在Python编程中,Mark Lutz提到了术语mixin。我有C/ c++ / c#的背景,以前没有听说过这个术语。什么是mixin?

从这个例子的字里行间(我链接了这个例子,因为它很长),我假设这是一个使用多重继承来扩展类的情况,而不是适当的子类化。这样对吗?

为什么我要这样做,而不是把新功能放到一个子类?就此而言,为什么混合/多重继承方法会比使用组合更好呢?

mixin与多重继承的区别是什么?这只是语义上的问题吗?


当前回答

我认为这里有一些很好的解释,但我想提供另一个角度。

In Scala, you can do mixins as has been described here but what is very interesting is that the mixins are actually 'fused' together to create a new kind of class to inherit from. In essence, you do not inherit from multiple classes/mixins, but rather, generate a new kind of class with all the properties of the mixin to inherit from. This makes sense since Scala is based on the JVM where multiple-inheritance is not currently supported (as of Java 8). This mixin class type, by the way, is a special type called a Trait in Scala.

它在定义类的方式中有所暗示: NewClass用SecondMixin和ThirdMixin扩展了FirstMixin …

我不确定CPython解释器是否做同样的事情(mixin class-composition),但我不会感到惊讶。同样,作为c++背景,我不会将ABC或“接口”称为等同于mixin——它们是类似的概念,但在使用和实现上有所不同。

其他回答

大致总结一下上面所有的好答案:

                States        /     Methods Concrete Method Abstract Method
Concrete State Class Abstract Class
Abstract State Mixin Interface

Mixin提供了一种在类中添加功能的方法,即您可以通过将模块包含在所需的类中来与模块中定义的方法进行交互。虽然ruby不支持多重继承,但提供了mixin作为实现这一目标的替代方案。

下面是一个示例,说明如何使用mixin实现多重继承。

module A    # you create a module
    def a1  # lets have a method 'a1' in it
    end
    def a2  # Another method 'a2'
    end
end

module B    # let's say we have another module
    def b1  # A method 'b1'
    end
    def b2  #another method b2
    end
end

class Sample    # we create a class 'Sample'
    include A   # including module 'A' in the class 'Sample' (mixin)
    include B   # including module B as well

    def S1      #class 'Sample' contains a method 's1'
    end
end

samp = Sample.new    # creating an instance object 'samp'

# we can access methods from module A and B in our class(power of mixin)

samp.a1     # accessing method 'a1' from module A
samp.a2     # accessing method 'a2' from module A
samp.b1     # accessing method 'b1' from module B
samp.b2     # accessing method 'a2' from module B
samp.s1     # accessing method 's1' inside the class Sample

Mixins是编程中的一个概念,其中类提供功能,但并不用于实例化。Mixins的主要目的是提供独立的功能,最好是Mixins本身没有与其他Mixins的继承,并且避免状态。在Ruby等语言中,有一些直接的语言支持,但对于Python则没有。但是,您可以使用多类继承来执行Python中提供的功能。

我看了这个视频http://www.youtube.com/watch?v=v_uKI2NOLEM来了解mixin的基础知识。对于初学者来说,了解mixin的基础知识、它们的工作原理以及在实现它们时可能遇到的问题是非常有用的。

维基百科仍然是最好的:http://en.wikipedia.org/wiki/Mixin

我只是使用一个python mixin来实现python milters的单元测试。通常情况下,milter会与MTA交谈,这使得单元测试变得困难。测试mixin覆盖了与MTA对话的方法,并创建了一个由测试用例驱动的模拟环境。

所以,你使用一个未修改的milter应用程序,比如spfmilter,然后mixin TestBase,像这样:

class TestMilter(TestBase,spfmilter.spfMilter):
  def __init__(self):
    TestBase.__init__(self)
    spfmilter.config = spfmilter.Config()
    spfmilter.config.access_file = 'test/access.db'
    spfmilter.spfMilter.__init__(self)

然后,在milter应用程序的测试用例中使用TestMilter:

def testPass(self):
  milter = TestMilter()
  rc = milter.connect('mail.example.com',ip='192.0.2.1')
  self.assertEqual(rc,Milter.CONTINUE)
  rc = milter.feedMsg('test1',sender='good@example.com')
  self.assertEqual(rc,Milter.CONTINUE)
  milter.close()

http://pymilter.cvs.sourceforge.net/viewvc/pymilter/pymilter/Milter/test.py?revision=1.6&view=markup

我认为它们是使用多重继承的一种有纪律的方式——因为最终mixin只是另一个python类,它(可能)遵循称为mixin的类的约定。

我对Mixin的理解是:

添加方法但不添加实例变量(类常量是可以的) 仅从object继承(Python中)

通过这种方式,它限制了多重继承的潜在复杂性,并通过限制必须查看的位置(与完整的多重继承相比)使跟踪程序流程变得相当容易。它们类似于ruby模块。

如果我想添加实例变量(具有比单继承所允许的更大的灵活性),那么我倾向于组合。

话虽如此,我还见过名为XYZMixin的类确实有实例变量。