믹스 인이란 무엇이며 왜 유용합니까?
" Programming Python "에서 Mark Lutz는 "믹신"을 참조합니다. 저는 C / C ++ / C # 배경 출신이며 이전에 용어를 들어 본 적이 없습니다. 믹스 인이란?
이 예제 의 줄 사이 를 확장하기 위해 (매우 길기 때문에 링크했습니다), '적절한'서브 클래 싱이 아닌 클래스를 확장하기 위해 다중 상속을 사용하는 경우라고 가정합니다. 이게 옳은 거니?
새 기능을 하위 클래스에 넣는 대신 왜 그렇게하고 싶습니까? 그 문제에 대해 믹스 인 / 다중 상속 방식이 합성을 사용하는 것보다 더 나은 이유는 무엇입니까?
믹스 인과 다중 상속을 구분하는 것은 무엇입니까? 의미론의 문제입니까?
믹스 인은 특별한 종류의 다중 상속입니다. 믹스 인이 사용되는 두 가지 주요 상황이 있습니다.
- 수업에 많은 기능을 제공합니다.
- 많은 다른 클래스에서 하나의 특정 기능을 사용합니다.
1 번의 예를 들어, werkzeug의 요청 및 응답 시스템을 고려 하십시오 . 다음과 같이 만들 요청을 만들 수 있습니다.
from werkzeug import BaseRequest
class Request(BaseRequest):
pass
수락 헤더를 추가 비용으로
from werkzeug import BaseRequest, AcceptMixin
class Request(AcceptMixin, BaseRequest):
pass
수락 헤더, etag, 인증 및 사용자 에이전트 지원을 지원하는 요청 클래스에서 다음과 같이 할 수 있습니다.
from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin
class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
pass
차이는 미묘하지만 위의 예에서 mixin 클래스는 독립적으로 만들어지지 않습니다. 보다 많은 상속에서는 AuthenticationMixin
(예를 들어) 아마도 Authenticator
. 즉, 클래스는 아마도 독자적으로 설계 될 것입니다.
먼저 믹스 인은 다중 상속 언어로만 존재한다는 점에 유의해야합니다. Java 또는 C #에서는 믹스 인을 할 수 없습니다.
기본적으로 mixin은 하위 클래스에 대해 설명 기능과 다형성 공명을 제공하는 독립형 기본 유형입니다. C #으로 생각하고 필요한 것이 이미 구현되어 있기 때문에 구현할 수 있습니다. 당신은 그것으로부터 상속하고 그것의 기능으로부터 이익을 얻습니다.
믹스 인은 일반적으로 범위가 좁으며 확장 할 수 없습니다.
[편집-이유 :]
나는 당신이 물었 기 때문에 이유를 논의 할 생각합니다. 가장 큰 이점은 스스로 반복 할 필요가 있습니다. C #에서 믹스 인이 이익을 얻을 수있는 가장 큰 곳은 폐기 패턴 입니다. IDisposable을 구현할 때마다 거의 항상 동일한 패턴을 사용하여 원하지만 약간의 변형을 사용하여 기본 코드를 작성하고 다시 작성하게됩니다. 확장 가능한 폐기 믹스 인이 권한 부여 많은 추가 입력을 절약 할 수 있습니다.
[편집 2- 다른 질문에 답하기 위해]
믹스 인과 다중 상속을 구분하는 것은 무엇입니까? 의미론의 문제입니까?
예. 믹스 인과 표준 다중 상속의 차이는 단지 의미론의 문제입니다. 다중 상속이있는 클래스는 다중 상속의 일부로 믹스 인을 사용할 수 있습니다.
mixin의 요점은 상속 유형에 영향을주지 않고 상속을 통해 다른 유형에 "혼합"될 수있는 유형을 생성하는 동시에 해당 유형에 대해 몇 가지 유익한 기능을 제공하는 것입니다.
다시 말하지만 이미 구현 된 인터페이스를 생각해.
나는 주로 믹스 인을 지원하지 않는 언어로 개발하기 때문에 개인적으로 믹스 인을 사용하지 않습니다. 그래서 "ahah!"를 제공 할 괜찮은 예제를 만드는 데 정말 힘든 시간을 보내고 있습니다. 당신을위한 순간. 하지만 다시 해보겠습니다. 저는 인위적인 예를 사용할 것입니다. 대부분의 언어는 이미 어떤 식 으로든 기능을 제공하지만, 이것이 믹스 인을 만드는 방법을 설명 할 것입니다. 여기에 간다 :
XML과 생성 화 할 수있는 유형이 가정합니다. 유형이 유형의 데이터 값이 포함 된 XML 조각이 포함 된 패키지를 반환하는 "ToXML"메서드와 유형이있는 XML 조각에서 데이터 값을 구성 할 수 있습니다. "FromXML"을 제공합니다. 다시 말하지만 이것은 인위적인 실행 파일 스트림이나 언어 실행 라이브러리의 XML 작성기 클래스를 사용할 수 있습니다. 요점은 객체를 XML로 만들 화하고 XML에서 새 객체를 가져옵니다.
이 예에서 또 다른 중요한 점은 일반적인 방식 으로이 작업을 수행하려는 것입니다. "ToXML"및 "FromXML"메서드를 구현할 모든 유형에 대해 모든 유형이 작업을 수행하고 제대로 작동하는지 확인하는 몇 가지 일반적인 방법이 필요합니다. 코드 보충을 원합니다.
언어가 지원한다면 XmlSerializable 믹스 인을 만들어 작업을 수행 할 수 있습니다. 이 유형은 ToXML 및 FromXML 메소드를 구현합니다. 예제에서 중요하지 않은 경우 사용하면 ToXML에서 반환 된 XML 조각을 빌드하기 위해 혼합 된 모든 유형에서 필요한 모든 데이터를 수집 할 수 있습니다. FromXML이 다음과 같은 경우 해당 데이터를 복원 할 수 있습니다. 전화.
그리고 그게 다야. 이를 사용하는 모든 XML로 이루어진 상속 화해야하는 모든 형식이 XmlSerializable에서 상속됩니다. ToXML 또는 FromXML을 호출하기 만하면됩니다. XmlSerializable은 완전한 형식이고 다형성 처음으로 형식에 대해 전혀 알지 못하는 문서 serializer를 만들 수 있습니다. 예를 들어 XmlSerializable 형식의 배열 만 허용합니다.
이제 혼합하는 모든 것이 모든 메서드 호출을 기록하는 mixin을 생성하거나 혼합하는 유형에 트랜잭션을 제공하는 mixin을 만드는 것과 같은 다른 작업 에이 시나리오를 사용하는 상상해에서. 목록은 계속 될 수 있습니다.
믹스 인을 해당 유형에 영향을주지 않고 유형에 소량의 기능을 추가하도록 작은 기본 유형으로 생각한다면 황금입니다.
바라건대. :)
이 답변은 믹스 인을 다음 과 같은 예제 로 설명하는 것을 목표로합니다 .
self-contained : 짧고, 예제를 이해하기 위해 라이브러리를 알 필요가 없습니다.
다른 언어가 아닌 Python 에서.
루비와 같은 다른 언어의 예가 해당 언어 에서 훨씬 더 일반적이기 때문에 이해할 수 있지만 이것은 파이썬 스레드입니다.
또한 논란이되는 질문을시기합니다.
믹스 인을 특성화하기 위해 다중 상속이 필요합니까?
정의
"권위있는"소스에서 믹스 인이 무엇인지 명확하게 말하는 "권위있는"출처의 인용을 아직 찾을 수 없습니다.
나는 믹스 인의 2 가지 가능한 정의를 의미 고 (추상베이스와 같은 다른 개념과 다른 내용되는 경우) 사람들은 어느 것이 옳은 것이지에 대해 동의하지 않습니다.
모든 언어마다 다를 수 있습니다.
정의 1 : 다중 상속 없음
믹스 인은 클래스의 일부 메서드가 클래스에 정의되지 않은 메서드를 사용하는 클래스입니다.
따라서 기본 클래스는 인스턴스화되는 것이 기본 클래스로 사용됩니다. 도킹 인스턴스에 예외를 발생시키는 호출 할 수없는 메서드가 있습니다.
일부 소스가 추가하는 제약은 클래스가 데이터가 아니라 방법 만 포함 할 수있는 것입니다. 그러나 이것이 왜 필요한지 모르겠습니다. 그러나 사용하기 많은 유용한 믹스 인에는 데이터가 사용하기 더 간단합니다.
고전적인 예는 <=
및 의 모든 비교 연산자를 구현 한 것입니다 ==
.
class ComparableMixin(object):
"""This class has methods which use `<=` and `==`,
but this class does NOT implement those methods."""
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
return self <= other and (self != other)
def __gt__(self, other):
return not self <= other
def __ge__(self, other):
return self == other or self > other
class Integer(ComparableMixin):
def __init__(self, i):
self.i = i
def __le__(self, other):
return self.i <= other.i
def __eq__(self, other):
return self.i == other.i
assert Integer(0) < Integer(1)
assert Integer(0) != Integer(1)
assert Integer(1) > Integer(0)
assert Integer(1) >= Integer(1)
# It is possible to instantiate a mixin:
o = ComparableMixin()
# but one of its methods raise an exception:
#o != o
이 특별한 예는 functools.total_ordering()
데코레이터 를 통해 얻을 수 있었지만 여기서 게임은 바퀴를 재발 명하는 것이 었습니다.
import functools
@functools.total_ordering
class Integer(object):
def __init__(self, i):
self.i = i
def __le__(self, other):
return self.i <= other.i
def __eq__(self, other):
return self.i == other.i
assert Integer(0) < Integer(1)
assert Integer(0) != Integer(1)
assert Integer(1) > Integer(0)
assert Integer(1) >= Integer(1)
정의 2 : 다중 상속
믹스 인은 기본 클래스의 일부 메소드가 정의하지 않은 메소드를 사용하는 디자인 패턴이며, 해당 메소드는 정의 1에서와 같이 파생되는 것이 아니라 다른 기본 클래스에 의해 구현 됩니다.
mixin 클래스 라는 용어 는 해당 디자인 패턴에서 사용하는 의도 된 기본 클래스를 나타냅니다 (메소드를 사용하는 사람들을 TODO 또는 그것을 구현하는 사람들?)
주어진 클래스가 믹스인인 지 아닌지를 결정하는 것은 쉽지 않습니다. 메서드는 파생 클래스에서 구현 될 수 있습니다.이 경우 정의 1로 돌아갑니다. 작성자의 의도를 일정합니다.
이 패턴은 다양한 기본 클래스 선택으로 기능을 다시 결합 할 수 있기 때문에 흥미 롭습니다.
class HasMethod1(object):
def method(self):
return 1
class HasMethod2(object):
def method(self):
return 2
class UsesMethod10(object):
def usesMethod(self):
return self.method() + 10
class UsesMethod20(object):
def usesMethod(self):
return self.method() + 20
class C1_10(HasMethod1, UsesMethod10): pass
class C1_20(HasMethod1, UsesMethod20): pass
class C2_10(HasMethod2, UsesMethod10): pass
class C2_20(HasMethod2, UsesMethod20): pass
assert C1_10().usesMethod() == 11
assert C1_20().usesMethod() == 21
assert C2_10().usesMethod() == 12
assert C2_20().usesMethod() == 22
# Nothing prevents implementing the method
# on the base class like in Definition 1:
class C3_10(UsesMethod10):
def method(self):
return 3
assert C3_10().usesMethod() == 13
존재 수있는 Python 발생
collections.abc에 대한 공식 문서 에서 문서는 Mixin Methods 라는 용어를 명시 적으로 사용합니다 .
클래스가 다음과 같은 경우
- 구현
__next__
- 단일 클래스에서 상속
Iterator
그런 다음 클래스는 무료 로 __iter__
mixin 메소드 를 얻습니다 .
하나는 다중 상속이 필요하지 않습니다 .
물론 문서는 다른 지점에서 모순이 될 수있는 다른 중요한 Python 라이브러리가 문서에서 다른 정의를 사용할 수 있습니다.
이 페이지는 또한라는 용어를 사용하는데 Set mixin
, 이는 즉 클래스가 Mixin 클래스 Set
와 같고 Iterator
호출 될 수 있음을 분명히 암시합니다 .
다른 언어로
Ruby : Ruby 프로그래밍 Ruby 및 The Ruby 프로그래밍 언어와 같은 주요 참고서에서 언급했듯이 믹스 인에 대한 다중 상속이 필요하지 않습니다.
C ++ : 구현되지 않은 메서드는 순수 가상 메서드입니다.
정의 1은 추상 클래스 (순수한 가상 메서드가있는 클래스)의 정의와 일치합니다. 해당 클래스는 인스턴스화 할 수 없습니다.
정의 2는 가상 상속으로 가능합니다. 두 개의 파생 클래스에서 다중 상속
저는 다중 상속을 사용하는 훈련 방법이라고 생각합니다. 거기로 mixin은 mixin이라고하는 클래스에 대한 규칙을 따르는 또 다른 용어 클래스이기 때문입니다.
Mixin이라고 부르는 것을 통제하는 규칙에 대한 나의 이해는 Mixin입니다.
- 메서드는 추가하지만 인스턴스 변수는 추가하지 않습니다 (클래스 상수는 괜찮습니다).
object
(Python에서) 상속 만
이렇게하면 다중 상속의 고급 자산을 제한하고 (전체 상속과 비교하여) 확인해야하는 위치를 제한하여 프로그램의 흐름을 추적 할 수 있습니다. 루비 모듈 과 사고 합니다 .
인스턴스 변수를 추가 비용 (단일 상속에서 허용하는 것보다 더 많은 유연성으로) 구성하는 경향이 있습니다.
그래도 인스턴스 변수가있는 XYZMixin이라는 클래스를 보았습니다.
Mixins는 클래스가 기능을 제공하지만 사용되지 않는 프로그래밍의 개념입니다. Mixins의 주요 목적은 독립형 기능을 제공하고, mixin 자체가 다른 mixin과 상속되지 않고 상태를 피하는 것이 가장 좋습니다. Ruby와 같은 언어 언어 지원 언어 지원이 Python에는 지원되지 않습니다. 그러나 다중 클래스 상속을 사용하여 Python에서 제공하는 기능을 사용할 수 있습니다.
믹스 인의 기본을 이해하기 위해 http://www.youtube.com/watch?v=v_uKI2NOLEM 동영상을 시청했습니다 . 믹스 인의 기본 사항과 믹스 인의 작동 방식 및이를 구현할 때 직면 할 수있는 문제를 이해하는 것이 매우 유용합니다.
Wikipedia는 여전히 최고입니다 : http://en.wikipedia.org/wiki/Mixin
믹스 인과 다중 상속을 구분하는 것은 무엇입니까? 의미론의 문제입니까?
믹스 인은 하나 형태의 다중 상속입니다. 일부 언어에서는 클래스에 믹스 인을 추가하는 코드가 상속의 일부 언어에서는 약간의 언어가 있습니다.
특히 Python의 맥락에서 mixin은 하위 클래스에 기능을 제공하지만 자체적으로 인스턴스화되지 않는 상위 클래스입니다.
"그것은 혼합 인이 아닌 다중 상속 일"이라고 말하는 원인은 혼합 인에 대해 혼동 될 수있는 클래스가 실제로 인스턴스화되고 수있는 것이 있는지 여부입니다. 따라서 실제로는 매우 실제적인 차이입니다.
다중 상속의 예
문서 의이 예 는 OrderedCounter입니다.
class OrderedCounter(Counter, OrderedDict): 'Counter that remembers the order elements are first encountered' def __repr__(self): return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) def __reduce__(self): return self.__class__, (OrderedDict(self),)
모듈 에서 Counter
및을 모두 서브 클래스합니다 .OrderedDict
collections
Counter
및 둘 다 OrderedDict
인스턴스화되어 자체적으로 사용됩니다. 그러나 둘 다 서브 클래에서 우리는 순서가 지정되고 각의 코드를 연속하는 카운터를 번거롭게합니다.
이것은 코드를 수행하는 강력한 방법이지만 문제가 될 수도 있습니다. 클래스 중 하나에 버그가있는 것으로 밝혀지면 부주의하게 수정하면 하위에 버그가 있습니다.
Mixin의 예
믹스 인은 일반적으로 OrderedCounter와 같은 협력 적 다중 상속이 발생하는 코드를 함께 할 수있는 방법으로 홍보됩니다. 믹스 인을 사용할 때 데이터와 결합되지 않은 기능을 사용합니다.
위의 예와 달리 믹스 인은 단독으로 사용할 수 없습니다. 새롭거나 다른 기능을 제공합니다.
예를 들어, 표준 라이브러리에는 라이브러리에 몇 가지 믹스 인이 socketserver
있습니다 .
이러한 혼합 클래스를 사용하여 각 서버 유형의 포크 및 스레딩 버전을 만들 수 있습니다. 예를 들어 ThreadingUDPServer는 다음과 같이 생성됩니다.
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
믹스 인 클래스는 UDPServer에 정의 된 메소드를 재정의하기 때문에 먼저 제공됩니다. 다양한 속성을 설정하면 기본 서버의 다양한 동작도 변경됩니다.
이 경우 mixin 메서드 UDPServer
는 동시성을 허용하기 위해 개체 정의 의 메서드를 재정의합니다 .
재정의 된 메서드는 인 것처럼 보이며 process_request
다른 메서드 인 process_request_thread
. 다음은 소스 코드 에서 다양한 것입니다 .
class ThreadingMixIn: """Mix-in class to handle each request in a new thread.""" # Decides how threads will act upon termination of the # main process daemon_threads = False def process_request_thread(self, request, client_address): """Same as in BaseServer but as a thread. In addition, exception handling is done here. """ try: self.finish_request(request, client_address) except Exception: self.handle_error(request, client_address) finally: self.shutdown_request(request) def process_request(self, request, client_address): """Start a new thread to process the request.""" t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads t.start()
의심스러운 예
이것은 주로 주로 사용되는 믹스 인입니다. 대부분의 수업은 유용성 이상으로 발전합니다.
class SimpleInitReprMixin(object):
"""mixin, don't instantiate - useful for classes instantiable
by keyword arguments to their __init__ method.
"""
__slots__ = () # allow subclasses to use __slots__ to prevent __dict__
def __repr__(self):
kwarg_strings = []
d = getattr(self, '__dict__', None)
if d is not None:
for k, v in d.items():
kwarg_strings.append('{k}={v}'.format(k=k, v=repr(v)))
slots = getattr(self, '__slots__', None)
if slots is not None:
for k in slots:
v = getattr(self, k, None)
kwarg_strings.append('{k}={v}'.format(k=k, v=repr(v)))
return '{name}({kwargs})'.format(
name=type(self).__name__,
kwargs=', '.join(kwarg_strings)
)
그리고 사용법은 다음과 가변합니다.
class Foo(SimpleInitReprMixin): # add other mixins and/or extend another class here
__slots__ = 'foo',
def __init__(self, foo=None):
self.foo = foo
super(Foo, self).__init__()
그리고 사용법 :
>>> f1 = Foo('bar')
>>> f2 = Foo()
>>> f1
Foo(foo='bar')
>>> f2
Foo(foo=None)
다른 방법을 사용하는 구성 또는 새로운 Python 코드에서 믹스 인을 사용하지 않는 것이 좋습니다 (예 : 상속받은 자신의 클래스에 대한 몽키 패치 메서드). 노력.
구식 클래스에서는 다른 클래스에서 몇 가지 메소드를 가져 오는 방법으로 믹스 인을 사용할 수 있습니다. 그러나 새로운 스타일의 세계에서는 믹스 인을 모두 포함 object
합니다. 즉, 다중 상속을 사용하면 자연스럽게 MRO 문제가 발생 합니다.
다중 상속 MRO가 작동하는 방법이 있습니다. 특히 super () 함수가 가장 많이 지지만, 이것은 super ()를 사용하여 전체 클래스 계층 구조를 수행해야하고 제어 흐름을 이해하는 것이 훨씬 더 어렵습니다.
여기에 좋은 설명이 생각하지만 다른 관점을 제공하고 싶었습니다.
Scala에서는 믹스 인을 수행 할 수 있습니다. 매우 흥미로운 믹스 인이 실제로 '융합'되어 상속 할 새로운 종류의 클래스를 생성하는 것입니다. 기본으로, 여러 클래스 / 믹스에서 상속하지 않고 상속 할 믹스 인의 모든 속성을 가진 새로운 종류의 클래스를 생성합니다. 이것은 Scala가 현재 다중 상속이 지원되지 않는 JVM을 기반으로하기 때문에 (Java 8 기준)입니다. 그런데이 mixin 클래스 유형은 Scala에서 Trait이라는 특수 유형입니다.
클래스가 정의되는 방식에 암시되어 있습니다. NewClass 클래스는 FirstMixin과 SecondMixin을 ThirdMixin으로 확장합니다.
CPython 인터프리터가 동일한 작업을 수행하는지 (mixin class-composition) 확실하지 않을 것입니다. 또한 C ++ 배경에서 왔기 때문에 믹스 인과 동등한 ABC 또는 '인터페이스'라고 부르지 않을 것입니다. 계속 개념이지만 사용 및 구현이 있습니다.
몇 가지 예가 도움이 될 것입니다.
클래스를 만들고 그것이 딕셔너리처럼 작동하기를 __ __
필요한 모든 메소드를 정의 할 수 있습니다 . 그러나 그것은 약간의 고통입니다. 대안으로, 몇 개만 정의하고 다른 상속에 추가하여 UserDict.DictMixin
( collections.DictMixin
py3k 로 이동 )에서 상속 할 수 있습니다. 나머지 사전 API를 자동으로 정의하는 효과가 있습니다.
두 번째 예 : GUI 툴킷 wxPython을 사용하면 여러 열 (예 : Windows 탐색기의 파일 표시)이있는 목록 제어를 만들 수 있습니다. 기본적으로 기본적입니다. 열 머리글을 클릭하고 ListCtrl에서 상속하고 적절한 믹스 인을 추가하여 특정 열을 기준으로 목록을 정렬하는 기능과 같은 추가 기능을 추가 할 수 있습니다.
파이썬 예제는 아니지만 D 언어 에서이 프로그래밍 용어 는 거의 같은 방식으로 사용되는 구조를 가리키는 데 사용됩니다. 수업에 물건 더미를 추가합니다.mixin
D에서는 (그런데 MI를 수행하지 않음) 템플릿을 범위에 삽입하여 수행합니다 (구문 적으로 인식하고 안전한 매크로를 생각하면 가깝습니다). 이를 통해 클래스, 계층, 함수, 모듈 등의 코드 한 줄을 여러 선언으로 확장 할 수 있습니다.
루비의 예가 도움이 될 수 있습니다.
mixin을 포함하고 Comparable
하나의 기능을 정의 할 수 있습니다. "<=>(other)"
mixin은 모든 기능을 제공합니다.
<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)
<=>(other)
올바른 결과 를 호출 하고 돌려줌이를 수행합니다.
"instance <=> other"
두 개체가 모두 같으면 0을 반환하고, instance
크기가 크면 other
0보다 작 으면 0을 반환 other
합니다.
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
방금 믹스 인을 사용하여 기술 밀터에 대한 단위 테스트를 구현했습니다. 일반적으로 milter는 MTA와 대화식 단위 테스트가 어렵습니다. 테스트 믹스 인은 MTA와 통신하는 방법을 재정의하고 대신 테스트 사례에 의해 구동되는 시뮬레이션 환경을 만듭니다.
따라서 spfmilter와 같은 수정되지 않은 milter 응용 프로그램을 사용하고 다음과 같이 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
OP는 C ++에서 mixin에 대해 들어 본 적이 없다고 말했습니다. 아마도 C ++에서 CRTP (Curiously Recurring Template Pattern)라고 불리기 때문일 것입니다. 또한 @Ciro Santilli는 mixin이 C ++의 추상 기본 클래스를 통해 구현된다고 언급했습니다. 추상 기본 클래스를 사용하여 믹스 인을 구현할 수 있지만 런타임시 가상 테이블 조회 오버 헤드없이 컴파일 타임에 템플릿을 사용하여 런타임에 가상 함수의 기능을 얻을 수 있으므로 과잉입니다.
아래 템플릿 클래스를 사용하여 @Ciro Santilli의 답변에서 Python 예제를 C ++로 변환했습니다.
#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 개체가 생성 될 때 보호 된 생성자가 컴파일 오류를 발생시키는 방법을 보여주기 위해 예제를 업데이트했습니다.
나는 당신이 ac # 배경을 가지고 있다고 읽었습니다. 따라서 좋은 출발점은 .NET 용 믹스 인 구현 일 수 있습니다.
http://remix.codeplex.com/ 에서 codeplex 프로젝트를 확인할 수 있습니다.
개요를 보려면 lang.net 심포지엄 링크를보십시오. codeplex 페이지에 대한 문서에는 아직 더 많은 것이 있습니다.
스테판 안부
참고 URL : https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-are-they-useful
'ProgramingTip' 카테고리의 다른 글
포트와 소켓의 차이점은 무엇입니까? (0) | 2020.09.28 |
---|---|
JavaScript에서 배열을 비교하는 방법은 무엇입니까? (0) | 2020.09.28 |
'git reset --hard HEAD'를 사용하여 이전 커밋으로 되돌리려면 어떻게해야합니까? (0) | 2020.09.28 |
명령 줄에서 모든 환경 변수 (0) | 2020.09.28 |
Scala 2.8 컬렉션 라이브러리는 "역사상 가장 긴 자살 기록"의 사례입니까? (0) | 2020.09.28 |