#include <iostream>
#include <assert.h>
template <class T>
class ComparableMixin {
public:
bool operator !=(ComparableMixin &other) {
return ~(*static_cast<T*>(this) == static_cast<T&>(other));
}
bool operator <(ComparableMixin &other) {
return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
}
bool operator >(ComparableMixin &other) {
return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
}
bool operator >=(ComparableMixin &other) {
return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
}
protected:
ComparableMixin() {}
};
class Integer: public ComparableMixin<Integer> {
public:
Integer(int i) {
this->i = i;
}
int i;
bool operator <=(Integer &other) {
return (this->i <= other.i);
}
bool operator ==(Integer &other) {
return (this->i == other.i);
}
};
int main() {
Integer i(0) ;
Integer j(1) ;
//ComparableMixin<Integer> c; // this will cause compilation error because constructor is protected.
assert (i < j );
assert (i != j);
assert (j > i);
assert (j >= i);
return 0;
}
编辑:在ComparableMixin中添加了受保护的构造函数,以便只能继承而不是实例化。更新示例以展示当创建ComparableMixin对象时,受保护构造函数将导致编译错误。
如果可能的话,我建议在新的Python代码中不要使用mix-ins(混入),而是采用其他方式(例如组合代替继承或将方法添加到自己的类中),这样做并不需要更多的努力。
在旧式类中,您可以使用mix-ins作为从另一个类中获取几个方法的一种方式。但在新式世界中,即使mix-in也会继承自object
。这意味着任何多重继承的使用都会自然引入MRO问题。
有方法可以使Python的多重继承MRO工作,最 notable 的是super()函数,但这意味着您必须使用super()完成整个类层次结构,并且它的流程控制难度相当大。
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
我刚刚使用了一个 Python mixin 来为 Python milter 实现单元测试。通常,milter 会与 MTA 进行通信,这使得单元测试变得困难。测试 mixin 覆盖了与 MTA 通信的方法,并创建了一个由测试用例驱动的模拟环境。
因此,您可以像这样将未修改的 milter 应用程序(例如 spfmilter)和 TestBase mixin 结合使用:
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)
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
"<=>(other)"
,这个mixin会提供以下所有函数:<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)
<=>(other)
并返回正确结果来实现此目的。
"instance <=> other"
如果两个对象相等,则返回0,如果instance
大于other
,则返回小于0的值,如果other
大于instance
,则返回大于0的值。__lt__
定义为基础,而不是已被弃用且不建议使用的__cmp__
。对我来说,使用那个mixin似乎比使用相当复杂的装饰器(functools
的一部分)更简单 - 尽管这个 可以更动态地响应提供的比较... - Tobias Kienzler我了解到您有一定的C#背景,因此一个不错的起点可能是.NET的mixin实现。
您可以查看这个codeplex项目:http://remix.codeplex.com/
观看lang.net Symposium链接以获得概述。在codeplex页面上仍有更多文档说明。
祝好! Stefan
状态 / 方法 | 具体方法 | 抽象方法 |
---|---|---|
具体状态 | 类 | 抽象类 |
抽象状态 | 混合 | 接口 |