믹스 인이란 무엇이며 왜 유용합니까?


953

" Programming Python "에서 Mark Lutz는 "mixins"를 언급합니다. 나는 C / C ++ / C # 배경에서 왔으며 이전 용어를 듣지 못했습니다. 믹스 인이란 무엇입니까?

이 예제 의 행 사이를 읽으면 (매우 길기 때문에 연결되어 있음), '상당한'하위 클래스와 달리 클래스를 확장하기 위해 다중 상속을 사용하는 경우라고 가정합니다. 이게 옳은 거니?

새로운 기능을 서브 클래스에 넣는 대신 왜 그렇게하고 싶습니까? 그 점에서 왜 믹스 인 / 멀티 상속 방법이 컴포지션을 사용하는 것보다 낫습니까?

믹스 인과 다중 상속을 분리하는 것은 무엇입니까? 의미론의 문제 일까?

답변:


709

믹스 인은 특별한 종류의 다중 상속입니다. 믹스 인이 사용되는 두 가지 주요 상황이 있습니다.

  1. 수업에 많은 옵션 기능을 제공하려고합니다.
  2. 많은 다른 클래스에서 하나의 특정 기능을 사용하려고합니다.

첫 번째 예는 werkzeug의 요청 및 응답 시스템을 고려 하십시오 . 다음과 같이 말하면 오래된 요청 객체를 만들 수 있습니다.

from werkzeug import BaseRequest

class Request(BaseRequest):
    pass

수락 헤더 지원을 추가하려면

from werkzeug import BaseRequest, AcceptMixin

class Request(AcceptMixin, BaseRequest):
    pass

헤더, etags, 인증 및 사용자 에이전트 지원을 지원하는 요청 오브젝트를 작성하려면 다음을 수행하십시오.

from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin

class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
    pass

차이점은 미묘하지만 위의 예에서 믹스 인 클래스는 독자적으로 만들어지지 않았습니다. 보다 전통적인 다중 상속에서 AuthenticationMixin(예를 들어)는 아마도 더 비슷할 것 Authenticator입니다. 즉, 수업은 아마도 독자적으로 설 수 있도록 설계되었을 것입니다.


123
세 번째 상황은 클래스에 많은 (선택 사항이 아닌) 기능을 제공하고 싶지만 별도의 클래스 (및 별도의 모듈)의 기능을 원하므로 각 모듈은 하나의 기능 (행동)입니다. 재사용을 위해, 그러나 구획화를 위해.
bootchk

60
이 예제에서는 문제가되지 않지만 일반적으로 상속 체인을 만들기 위해 기본 기본 클래스를 괄호 안에 마지막 요소로 지정하려고합니다. Request ==> Mixin ==> ... ==> BaseRequest. 여기를보십시오 : ianlewis.org/en/mixins-and-python
hillel

10
@hillel 좋은 지적이지만 파이썬은 왼쪽에서 오른쪽으로 슈퍼 클래스의 메소드를 호출한다는 것을 명심하십시오 (예를 들어 생성자를 재정의 해야하는 경우).
Eliseu Monar dos Santos

9
이것은 데코레이터 디자인 패턴처럼 많이 들립니다.
D-Jones

4
4 번째 상황은 다음과 같습니다 거기에 기존의 가족 이미 Parent클래스와 Child1, Child2, ChildN제 3 자 라이브러리 내부의 서브 클래스, 당신은 전체 가족을위한 사용자 정의 동작을합니다. 이상적으로 이러한 동작을에 추가 Parent하고 타사 라이브러리 개발자가 풀 요청을 가져 오기를 바랍니다. 그렇지 않으면 당신은 당신의 자신을 구현해야 할 것 class NewBehaviorMixin같은 래퍼 클래스의 전체 세트, 그리고 정의 class NewParent(NewBehaviorMixin, Parent): passclass NewChildN(NewBehaviorMixin, ChildN): pass등 : (PS 당신은 더 좋은 방법을 알고 있습니까?)
RayLuo

240

먼저 믹스 인은 다중 상속 언어로만 존재합니다. Java 또는 C #에서는 믹스 인을 수행 할 수 없습니다.

기본적으로 믹스 인은 하위 클래스에 대해 제한된 기능과 다형성 공명을 제공하는 독립형 기본 유형입니다. C #으로 생각하고 있다면 이미 구현 되었기 때문에 실제로 구현할 필요가없는 인터페이스를 생각해보십시오. 당신은 그것에서 상속하고 그 기능으로부터 이익을 얻습니다.

믹스 인은 일반적으로 범위가 좁으며 확장되지 않습니다.

[편집-이유에 관해서 :]

당신이 요청한 이후 왜 그런지 설명해야한다고 생각합니다. 가장 큰 장점은 반복해서 스스로 할 필요가 없다는 것입니다. C #에서 믹스 인이 혜택을 얻을 수있는 가장 큰 장소는 Disposal 패턴 일 수 있습니다 . IDisposable을 구현할 때마다 거의 항상 동일한 패턴을 따르고 싶지만 약간의 변형으로 동일한 기본 코드를 작성하고 다시 작성하게됩니다. 확장 가능한 폐기 믹스 인이 있다면 추가 타이핑을 많이 줄일 수 있습니다.

[편집 2-다른 질문에 대답하기 위해]

믹스 인과 다중 상속을 분리하는 것은 무엇입니까? 의미론의 문제 일까?

예. 믹스 인과 표준 다중 상속의 차이점은 의미론의 문제 일뿐입니다. 다중 상속이있는 클래스는 다중 상속의 일부로 믹스 인을 활용할 수 있습니다.

믹스 인의 요점은 상속 유형에 영향을주지 않으면 서 상속을 통해 다른 유형에 "혼합"될 수있는 유형을 생성하는 동시에 해당 유형에 유용한 기능을 제공하는 것입니다.

다시 한 번 이미 구현 된 인터페이스를 생각해보십시오.

나는 개인적으로 믹스 인을 지원하지 않는 언어로 개발하기 때문에 개인적으로 믹스 인을 사용하지 않기 때문에 "ahah"를 제공하는 훌륭한 예를 생각해내는 데 정말 어려운 시간을 보내고 있습니다. 당신을위한 순간. 하지만 다시 시도하겠습니다. 나는 대부분의 언어가 이미 어떤 방식 으로든 그 기능을 제공하는 것으로 고안된 예제를 사용할 것입니다. 그러나 믹스 인이 어떻게 만들어지고 사용되는지를 설명 할 것입니다. 간다 :

XML로 직렬화하거나 XML에서 직렬화 할 수있는 유형이 있다고 가정하십시오. 형식에 형식의 데이터 값이있는 XML 조각이 포함 된 문자열을 반환하는 "ToXML"메서드와 형식이 문자열의 XML 조각에서 데이터 값을 재구성 할 수있는 "FromXML"형식을 제공하려고합니다. 다시 한 번, 이것은 고안된 예이므로 아마도 언어의 런타임 라이브러리에서 파일 스트림 또는 XML Writer 클래스를 사용할 것입니다. 요점은 객체를 XML로 직렬화하고 XML에서 새 객체를 가져오고 싶다는 것입니다.

이 예제에서 다른 중요한 점은 일반적인 방법으로이 작업을 수행한다는 것입니다. 직렬화하려는 모든 유형에 대해 "ToXML"및 "FromXML"메소드를 구현할 필요가 없으며, 유형이이를 수행하고 작동하도록하는 일반적인 수단을 원합니다. 코드 재사용을 원합니다.

언어가 지원하는 경우 XmlSerializable 믹스 인을 만들어서 작업을 수행 할 수 있습니다. 이 유형은 ToXML 및 FromXML 메소드를 구현합니다. 예제에 중요하지 않은 메커니즘을 사용하면 ToXML이 반환 한 XML 조각을 작성하기 위해 혼합 된 모든 유형에서 필요한 모든 데이터를 수집 할 수 있으며 FromXML이 전화했다.

그리고 그게 다야. 이를 사용하려면 XmlSerializable에서 상속 된 XML로 serialize해야하는 모든 유형이 있습니다. 해당 유형을 직렬화 또는 역 직렬화해야 할 때마다 ToXML 또는 FromXML을 호출하면됩니다. 실제로 XmlSerializable은 본격적인 유형이며 다형성이기 때문에 원본 유형에 대해 전혀 모르는 XmlSerializable 유형의 배열 만 받아들이는 문서 시리얼 라이저를 작성할 수 있습니다.

이제이 시나리오를 사용하여 믹스에서 모든 클래스를 혼합하는 모든 클래스 또는이를 혼합하는 유형에 트랜잭션 성을 제공하는 믹스 인을 작성하는 믹스 인 작성과 같은 다른 상황에 대해이 시나리오를 사용한다고 상상해보십시오.

믹스 인을 다른 유형에 영향을주지 않고 유형에 소량의 기능을 추가하도록 설계된 작은 기본 유형으로 생각하면 황금색입니다.

잘만되면 :)


25
"다형성 공명"이라는 문구가 마음에 드십니까? 스스로 만들었습니다. 내 생각에 어딘가 물리학에서 들었을 수도 있습니다.
Randolpho

50
첫 문장에 약간 동의하지 않습니다. 루비는 단일 상속 언어이며 믹스 인은 다른 클래스에서 상속받지 않고 주어진 클래스에 메소드를 추가하는 방법입니다.
Keltia

23
@Keltia : 믹스 인은 다중 상속이라고 생각합니다. 루비의 경우, 그들은 적절한 믹스 인이 아닌 원숭이 패치 (또는 다른 것)입니다. 루비 사람들은 이것을 믹스 인이라고 부를 수도 있지만, 다른 종류입니다.
S.Lott

10
사실, 진정한 믹스 인은 다중 상속을 사용할 수 없습니다. 믹스 인에는 상속하지 않고 한 클래스의 메소드, 속성 등이 포함됩니다. 이것은 코드 재사용의 이점을 다형성으로 보이는 경향이 있지만 부모 (죽음의 다이아몬드 등)를 결정하는 데는 문제가 없습니다. 믹스 인 지원 언어는 믹스 인 클래스의 일부를 포함하는 경향이 있습니다 지금 측면).
Trevor

8
레코드의 경우 Java는 이제 기본 메소드와의 믹스 인을 지원합니다.
shmosel

169

이 답변은 다음 과 같은 예제와 믹스 인을 설명하는 것을 목표로합니다 .

  • 자체 포함 : 짧고 예제를 이해하기 위해 라이브러리를 알 필요가 없습니다.

  • 다른 언어가 아닌 Python .

    Ruby와 같은 다른 언어의 예제가 있다는 것이 이해할 만합니다. 왜냐하면 용어는 해당 언어에서 훨씬 일반적이지만 파이썬 스레드입니다.

또한 논란의 여지가있는 질문을 고려해야한다.

믹스 인을 특성화하기 위해 다중 상속이 필요합니까?

정의

파이썬에서 믹스 인이 무엇인지 명확하게 말하는 "권한있는"출처의 인용을 아직 보지 못했습니다.

믹스 인에 대한 두 가지 가능한 정의를 보았으며 (추상적 인 기본 클래스와 같은 다른 유사한 개념과 다른 것으로 간주되는 경우) 사람들은 어느 것이 올바른지에 전적으로 동의하지 않습니다.

합의는 언어마다 다를 수 있습니다.

정의 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 클래스 라는 용어 는 해당 디자인 패턴에 사용되는 기본 클래스 (메소드를 사용하는 클래스 또는 메소드를 구현하는 클래스)를 나타냅니다.

주어진 클래스가 믹스 인인지 아닌지를 결정하는 것은 쉽지 않습니다. 메소드는 파생 클래스에서 구현 될 수 있습니다.이 경우 정의 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

권위있는 파이썬 어커런스

collections.abc에 대한 공식 문서 에서 설명서는 Mixin Methods 라는 용어를 명시 적으로 사용합니다 .

그것은 클래스라면 :

  • 구현하다 __next__
  • 단일 클래스에서 상속 Iterator

그런 다음 클래스는 무료 로 __iter__ mixin 메소드 를 얻습니다 .

따라서 최소한이 문서의 시점에서 mixin은 다중 상속을 요구하지 않으며 정의 1과 일치합니다.

물론 문서는 다른 시점에서 모순 될 수 있으며 다른 중요한 Python 라이브러리는 문서에서 다른 정의를 사용하고있을 수 있습니다.

이 페이지는 또한 용어를 사용합니다.이 용어 Set mixin는 클래스를 Mixin 클래스 Set와 같고 Iterator호출 할 수 있음을 명확하게 제안합니다 .

다른 언어로

  • Ruby : Programming Ruby 및 The Ruby programming Language와 같은 주요 참고서에서 언급 한 것처럼 mixin에 대해 다중 상속이 필요하지 않습니다.

  • C ++ : 구현되지 않은 메소드는 순수한 가상 메소드입니다.

    정의 1은 추상 클래스 (순수 가상 메서드가있는 클래스)의 정의와 일치합니다. 해당 클래스는 인스턴스화 할 수 없습니다.

    정의 2는 가상 상속으로 가능합니다. 두 개의 파생 클래스에서 다중 상속


37

나는 그것들을 다중 상속을 사용하는 훈련 된 방법으로 생각합니다. 궁극적으로 mixin은 mixin이라는 클래스에 대한 규칙을 따르는 다른 파이썬 클래스이기 때문입니다.

Mixin이라고 부르는 것을 지배하는 규칙에 대한 나의 이해는 Mixin입니다.

  • 메소드를 추가하지만 인스턴스 변수는 추가하지 않습니다 (클래스 상수는 정상 임)
  • 만 상속 object(파이썬)

그렇게하면 다중 상속의 잠재적 복잡성을 제한하고, 전체 다중 상속과 비교하여 볼 위치를 제한하여 프로그램 흐름을 합리적으로 쉽게 추적 할 수 있습니다. 그것들은 루비 모듈 과 비슷 합니다 .

인스턴스 변수를 추가하려면 (단일 상속으로 허용되는 것보다 유연성이 높음) 컴포지션을 선호합니다.

말했듯이 인스턴스 변수가있는 XYZMixin이라는 클래스를 보았습니다.


30

믹스 인은 프로그래밍에서 클래스가 기능을 제공하는 개념이지만 인스턴스화에는 사용되지 않습니다. 믹스 인의 주요 목적은 독립형 기능을 제공하는 것이며 믹스 인 자체가 다른 믹스 인과 상속되지 않고 상태를 피하는 것이 가장 좋습니다. Ruby와 같은 언어에는 직접적인 언어 지원이 있지만 Python의 경우에는 지원되지 않습니다. 그러나 다중 클래스 상속을 사용하여 Python에서 제공하는 기능을 실행할 수 있습니다.

믹스 인의 기본 사항을 이해하기 위해 http://www.youtube.com/watch?v=v_uKI2NOLEM 비디오를 보았습니다 . 초보자는 믹스 인의 기본 사항과 믹스 인의 작동 방식 및이를 구현할 때 직면 할 수있는 문제를 이해하는 것이 매우 유용합니다.

Wikipedia는 여전히 최고입니다 : http://en.wikipedia.org/wiki/Mixin


29

믹스 인과 다중 상속을 분리하는 것은 무엇입니까? 의미론의 문제 일까?

믹스 인은 제한된 형태의 다중 상속입니다. 일부 언어에서는 클래스에 믹스 인을 추가하는 메커니즘이 상속과 약간 다릅니다 (구문의 관점에서).

특히 파이썬과 관련하여 믹스 인은 서브 클래스에 기능을 제공하지만 인스턴스화되지는 않는 상위 클래스입니다.

"실제로 믹스 인이 아닌 다중 상속에 불과하다"고 말할 수있는 것은 믹스 인에 대해 혼란 스러울 수있는 클래스가 실제로 인스턴스화되어 사용될 수 있다면 실제로 의미 론적이며 매우 실질적인 차이입니다.

다중 상속의 예

documentation 의이 예제 는 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모듈.

모두 CounterOrderedDict인스턴스 자신에 사용하기위한 것입니다. 그러나 두 클래스를 모두 서브 클래 싱하면 카운터가 정렬되어 각 개체의 코드를 재사용 할 수 있습니다.

이것은 코드를 재사용하는 강력한 방법이지만 문제가 될 수도 있습니다. 객체 중 하나에 버그가있는 것으로 밝혀지면주의없이 수정하면 서브 클래스에 버그가 발생할 수 있습니다.

믹스 인의 예

믹스 인은 일반적으로 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()

고안된 예

이것은 대부분 데모 목적으로 사용되는 믹스 인입니다. 대부분의 객체는이 repr의 유용성을 넘어서 진화 할 것입니다.

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)

11

나는 여기에 좋은 설명이 있다고 생각하지만 다른 관점을 제공하고 싶었습니다.

스칼라에서는 여기에 설명 된대로 믹스 인을 수행 할 수 있지만 매우 흥미로운 점은 믹스 인이 실제로 '융합되어'상속 할 새로운 종류의 클래스를 생성한다는 것입니다. 본질적으로 여러 클래스 / 믹스 인에서 상속하는 것이 아니라 상속 할 믹스 인의 모든 속성을 사용하여 새로운 종류의 클래스를 생성합니다. Scala는 다중 상속이 현재 지원되지 않는 JVM을 기반으로하기 때문에 의미가 있습니다 (Java 8 기준). 그건 그렇고,이 믹스 인 클래스 유형은 스칼라의 특성이라고하는 특수 유형입니다.

클래스가 정의 된 방식으로 암시되었습니다 : NewClass 클래스는 ThirdMixin으로 FirstMixin을 ThirdMixin으로 확장합니다 ...

CPython 인터프리터가 동일한 작업을 수행하는지 확실하지 않지만 (mixin class-composition) 놀라지 않을 것입니다. 또한 C ++ 배경에서 나는 믹스 인에 해당하는 ABC 또는 '인터페이스'를 호출하지 않습니다. 유사한 개념이지만 사용 및 구현이 다양합니다.


9

새로운 파이썬 코드의 믹스 인에 대해 조언하지 않을 것입니다. 노력.

구식 클래스에서는 다른 클래스에서 몇 가지 메소드를 가져 오는 방법으로 믹스 인을 사용할 수 있습니다. 그러나 새로운 스타일의 세계에서는 심지어 믹스 인까지 모든 것이 상속됩니다 object. 다중 상속을 사용하면 자연스럽게 MRO 문제가 발생 합니다.

파이썬에서 다중 상속 MRO를 작동시키는 방법, 특히 super () 함수를 만드는 방법이 있지만 super ()를 사용하여 전체 클래스 계층 구조를 수행해야하며 제어 흐름을 이해하기가 훨씬 더 어렵습니다.


3
버전 2.3부터 Python은 Python 2.3 메소드 분석 순서 또는 메소드 분석 순서에 설명 된 "C3 메소드 분석"을 사용합니다 .
webwurst

11
개인적으로, 나는 대부분의 경우 원숭이 패치보다 믹스 인을 사용합니다. 코드를 추론하고 따르는 것이 더 쉽습니다.
tdammers

5
공감. 귀하의 답변은 개발 스타일에 대한 올바른 의견을 나타내지 만 실제 질문은 실제로 다루지는 않습니다.
Ryan B. Lynch

8

아마도 몇 가지 예가 도움이 될 것입니다.

클래스를 작성하고 있고 사전처럼 행동하기를 원하는 경우 __ __필요한 모든 다양한 방법을 정의 할 수 있습니다 . 그러나 그것은 약간의 고통입니다. 대안으로, 몇 가지를 정의하고 UserDict.DictMixin( collections.DictMixinpy3k에서 이동 한 )에서 ( 다른 상속과 함께) 상속 할 수 있습니다 . 이렇게하면 나머지 모든 사전 API를 자동으로 정의하는 효과가 있습니다.

두 번째 예 : GUI 툴킷 wxPython을 사용하면 여러 열 (예 : Windows 탐색기의 파일 표시)로 목록을 제어 할 수 있습니다. 기본적으로이 목록은 상당히 기본적입니다. ListCtrl에서 상속하고 적절한 믹스 인을 추가하여 열 머리글을 클릭하여 특정 열을 기준으로 목록을 정렬하는 기능과 같은 추가 기능을 추가 할 수 있습니다.


8

파이썬 예제는 아니지만 D 프로그래밍 언어에서이 용어 mixin는 거의 같은 방식으로 사용되는 구문을 나타내는 데 사용됩니다. 수업에 물건 더미를 추가합니다.

D에서 (MI를 수행하지 않는) 이것은 템플릿을 문법적으로 인식하고 안전한 매크로라고 생각하고 스코프에 삽입하여 수행됩니다. 이를 통해 클래스, 구조체, 함수, 모듈 또는 임의의 수의 선언으로 확장 할 수있는 단일 코드 행이 가능합니다.


2
Mixin은 D, Ruby 등에서 사용되는 일반적인 용어입니다. Wikipedia에 따르면 그것들은 구식 lisp 시스템에서 시작되었으며 1983 년에 처음으로 문서화되었습니다. en.wikipedia.org/wiki/…
Lee B

7

OP는 C ++에서 믹스 인에 대해 들어 본 적이 없다고 언급했습니다. 아마도 C ++에서는 CRTP (Curiously Recurring Template Pattern)라고 불리기 때문일 것입니다. 또한 @Ciro Santilli는 mixin이 C ++의 추상 기본 클래스를 통해 구현된다고 언급했습니다. 추상 기본 클래스를 사용하여 믹스 인을 구현할 수 있지만 런타임시 가상 테이블 조회의 오버 헤드없이 컴파일 타임에 템플리트를 사용하여 런타임시 가상 기능의 기능을 달성 할 수 있으므로 과도합니다.

CRTP 패턴은 여기 에 자세히 설명되어 있습니다

아래 템플릿 클래스를 사용하여 @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의 객체가 생성 될 때 보호 된 생성자가 컴파일 오류를 발생시키는 방법을 보여 주도록 예제를 업데이트했습니다.


C ++에서 믹스 인과 CRTP는 정확히 동일하지 않습니다.
ashrasmun 2019

6

루비의 예가 도움이 될 수 있습니다.

믹스 인을 포함하고 Comparable하나의 함수를 정의 할 수 있습니다. 믹스 인은 다음 과 "<=>(other)"같은 모든 함수를 제공합니다.

<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)

<=>(other)올바른 결과 를 호출 하고 돌려줌으로써이를 수행합니다.

"instance <=> other"0을 반환 두 객체가 0보다 작은, 동일한 경우 경우 instance보다 더 큰 other이상 0 경우가 other크다.


다음 은 Python에 비슷한 믹스 인을 제공하는 게시물입니다. 제안은 __lt__대신에 기본 으로 정의되지만 __cmp__후자는 실제로 사용되지 않으며 사용하지 않는 것이 좋습니다. 나에게 대신 매우 복잡의 믹스 인 사용하기 간단 보인다 장식 (의 일부 functools를 ) - 비록 이 하나 에 더 동적으로 반응 할 수도 있는 비교가 제공됩니다 ...
토비아스 Kienzler

6

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

4
이 상속과 다중 상속의 차이점은 무엇입니까?
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

차이점은 모듈에서 인스턴스를 생성 할 수 없지만 일반 클래스와 모듈간에 차이가없는 경우 믹스 인은 명백한 것이 아니며 일반 클래스가 어디에 있고 믹스 인이 어디에 있는지 이해하기 어렵습니다
ka8725

루비 믹스 인은 인스턴스화 할 수 없지만 다중 상속에 사용해야하는 클래스일까요?
Trilarion

6

방금 파이썬 믹스 인을 사용하여 파이썬 밀러에 대한 단위 테스트를 구현했습니다. 일반적으로 milter는 MTA와 대화하므로 단위 테스트가 어렵습니다. 테스트 믹스 인은 MTA와 통신하는 메소드를 대체하고 대신 테스트 케이스로 구동되는 시뮬레이션 환경을 작성합니다.

따라서 spfmilter와 같은 수정되지 않은 milter 응용 프로그램과 다음과 같이 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


4

이전 응답이 MixIns를 매우 잘 정의했다고 생각 합니다. 그러나 그것들을 더 잘 이해하기 위해 MixIns추상 클래스인터페이스 를 비교하는 것이 유용 할 수 있습니다 하려면 코드 / 구현 관점에서 .

1. 추상 클래스

  • 하나 이상의 추상 메소드를 포함해야하는 클래스

  • 추상 클래스 상태 (인스턴스 변수) 및 비추 상 메소드를 포함 할 수 있습니다.

2. 인터페이스

  • 인터페이스 에는 추상 메소드 포함 (추상적 이지 않은 메소드 및 내부 상태 없음)

3. 믹스 인

  • 인터페이스와 같은 MixIn 은 내부 상태 (인스턴스 변수)를 포함
  • MixIn 은 하나 이상의 비추 상 메소드 포함 합니다 ( 인터페이스와 달리 비추 상 메소드를 포함 할 수 있음 )

예를 들어 파이썬에서는 위의 모든 것이 classes 로 정의되어 있기 때문에 이것은 단지 규칙 입니다. 그러나 모두의 공통적 인 특징 추상 클래스, 인터페이스유지 mixin이 그들이다 해서는 안 자신의 존재, 즉 인스턴스화 할 수 없습니다.


3

AC # 배경이 있음을 읽었습니다. 따라서 좋은 출발점은 .NET에 대한 mixin 구현 일 수 있습니다.

코드 플렉스 프로젝트를 확인하고 싶을 수도 있습니다. http://remix.codeplex.com/

lang.net Symposium 링크를보고 개요를 확인하십시오. codeplex 페이지에 더 많은 문서가 있습니다.

스테판에 대하여

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.