source

믹스인이란 무엇이며 왜 유용한가?

manycodes 2023. 1. 9. 21:16
반응형

믹스인이란 무엇이며 왜 유용한가?

Programming 파이썬에서 Mark Lutz는 mixin이라는 용어를 언급합니다.저는 C/C++/C#배경에서 태어나서 이 용어를 들어본 적이 없습니다.믹스인이란?

이 예제의 행간을 읽어 보면(매우 길기 때문에 링크한 경우) 적절한 서브 분류가 아닌 여러 개의 상속을 사용하여 클래스를 확장하는 경우라고 가정합니다.이게 맞나

새로운 기능을 서브클래스에 넣는 것이 아니라 왜 그렇게 해야 합니까?그런 점에서 혼합/복수 상속 방식이 구성을 사용하는 것보다 더 나은 이유는 무엇입니까?

믹스인과 여러 상속을 구별하는 것은 무엇입니까?의미론적인 문제일까요?

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

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

1번 예시로 werkzeug의 요청응답 시스템을 고려하십시오.다음과 같이 함으로써 일반 오래된 요청 개체를 만들 수 있습니다.

from werkzeug import BaseRequest

class Request(BaseRequest):
    pass

Accept 헤더 지원을 추가하려면

from werkzeug import BaseRequest, AcceptMixin

class Request(AcceptMixin, BaseRequest):
    pass

Accept 헤더, 에태그, 인증 및 사용자 에이전트 지원을 지원하는 요청 개체를 만드는 경우 다음을 수행할 수 있습니다.

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

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

차이는 미묘하지만 위의 예에서는 믹스인 클래스가 자립하지 않았습니다.보다 전통적인 다중 상속에서는AuthenticationMixin를 들어는 아마 (어느 정도)라고 하는 이 더 거예요.Authenticator 이 는 아마 할 수 것입니다.

먼저 mixin은 여러 상속 언어에서만 존재함을 유의하십시오.Java 또는 C#에서는 믹스인을 할 수 없습니다.

기본적으로 mixin은 독립형 베이스 타입으로 자녀 클래스에 제한된 기능과 다형 공명을 제공합니다.C#을 생각하고 있는 경우는, 이미 실장되어 있기 때문에 실제로 실장할 필요가 없는 인터페이스에 대해 생각해 주세요.그냥 인터페이스를 계승해, 그 기능을 활용할 수 있습니다.

믹스인은 일반적으로 범위가 좁기 때문에 확장을 의도하지 않습니다.

[편집 --이유에 대하여:]

당신이 물어봤으니 이유를 말해야겠군요.가장 큰 장점은 스스로 그것을 반복할 필요가 없다는 것이다.C#에서 믹스인이 도움이 될 수 있는 가장 큰 장소는 폐기 패턴일 수 있습니다.IDisposable을 실장할 때는 거의 항상 같은 패턴을 따르지만, 결국 작은 차이로 같은 기본 코드를 쓰고 다시 씁니다.확장 가능한 Dispose mixin(폐기 믹스인)이 있으면 타이핑을 많이 줄일 수 있습니다.

[편집 2 - 기타 질문에 답변하기 위해]

믹스인과 여러 상속을 구별하는 것은 무엇입니까?의미론적인 문제일까요?

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

혼합의 요점은 상속 유형에 영향을 주지 않고 상속을 통해 다른 유형에 "혼합"할 수 있는 유형을 만들면서 해당 유형에 대해 몇 가지 유용한 기능을 제공하는 것입니다.

다시, 이미 실장되어 있는 인터페이스에 대해 생각해 봅시다.

저는 믹스인을 주로 지원하지 않는 언어로 개발하기 때문에 개인적으로 믹스인을 사용하지 않습니다.그래서 '아악'하는 순간을 제공하는 적절한 예를 생각해 내는 데 어려움을 겪고 있습니다.하지만 다시 해볼게.제가 의도된 예를 들어 보겠습니다.대부분의 언어는 이미 어떤 식으로든 기능을 제공하고 있습니다.그러나 이것이 믹스인의 작성과 사용법을 설명해 줄 것입니다.이하에, 이하를 참조해 주세요.

XML과 직렬화할 수 있는 유형이 있다고 가정합니다. 이 유형에서 XML 조각이 포함된 문자열을 형식의 데이터 값과 함께 반환하는 "ToXML" 메서드와 문자열의 XML 조각에서 데이터 값을 재구성할 수 있는 "FromXML"을 제공하려고 합니다.다시 말씀드리지만, 이것은 조작된 예이므로 파일 스트림이나 언어 런타임 라이브러리의 XML Writer 클래스를 사용할 수 있습니다.신경쓰지 말아요.여기서 중요한 것은 개체를 XML로 직렬화하고 XML에서 새 개체를 가져오는 것입니다.

이 예에서 또 다른 중요한 점은 일반적인 방법으로 이 작업을 수행하는 것입니다.시리얼화하는 모든 타입에 대해서 「ToXML」및 「FromXML」메서드를 실장할 필요는 없습니다.사용하는 타입이 이것을 실행해, 동작하는 것을 보증하는 일반적인 수단이 필요합니다.코드 재사용을 원하십니까?

언어에서 지원되는 경우 XmlSerializable 믹스인을 생성하여 작업을 수행할 수 있습니다.이 유형은 ToXML 및 FromXML 메서드를 구현합니다.이 예에서는 중요하지 않은 메커니즘을 사용하여 ToXML에 의해 반환되는 XML fragment를 구축하기 위해 혼합된 모든 유형에서 필요한 데이터를 수집할 수 있으며 FromXML이 호출되었을 때 해당 데이터를 똑같이 복원할 수 있습니다.

그리고.. 그게 다야이를 사용하려면 XmlSerializable에서 상속받은 XML에 대해 직렬화해야 하는 모든 유형이 있어야 합니다.그 타입을 시리얼화 또는 역직렬화 할 필요가 있을 때는 ToXML 또는 FromXML을 호출합니다.사실 XmlSerializable은 완전한 타입이며 다형성이기 때문에 원래 타입에 대해 전혀 모르는 문서시리얼라이저를 작성할 수 있습니다.예를 들어, xmlSerializable 타입의 배열만 받아들이면 됩니다.

이 시나리오를 다른 용도로 사용하는 경우를 생각해 보겠습니다.예를 들어 혼합된 모든 클래스가 모든 메서드콜을 로그에 기록하도록 하는 믹스인 작성이나 혼합된 유형에 트랜잭션성을 제공하는 믹스인 작성 등이 있습니다.목록은 계속 이어질 수 있습니다.

그 타입에 영향을 주지 않고 소량의 기능을 추가할 수 있도록 설계된 소형 베이스 타입이라고 생각하면 금상첨화입니다.

바라건대.:)

이 답변은 다음과 같은 예를 사용하여 mixin을 설명하는 것을 목적으로 합니다.

  • 자기 완결형: 예를 이해하기 위해 라이브러리를 알 필요가 없는 짧은 형식입니다.

  • 다른 언어가 아닌 Python으로 되어 있습니다.

    Ruby 등 다른 언어에서도 많이 사용되고 있기 때문에 예를 들 수 있지만, 이것은 Python 스레드입니다.

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

믹스인을 특징짓기 위해 다중 상속이 필요합니까?아니면 필요합니까?

정의들

Python의 믹스인이 무엇인지 명확하게 설명하는 "권위 있는" 출처의 인용문은 아직 보지 못했습니다.

나는 믹스인의 가능한 정의를 2개 보았다(추상 베이스 클래스 등 다른 유사한 개념과 다른 것으로 간주되는 경우). 그리고 사람들은 어느 것이 옳은지에 대해 완전히 동의하지 않는다.

언어에 따라 의견이 다를 수 있습니다.

정의 1: 다중 상속 없음

mixin은 클래스의 일부 메서드가 클래스에 정의되지 않은 메서드를 사용하는 클래스입니다.

따라서 클래스는 인스턴스화되지 않고 기본 클래스로 기능합니다.그렇지 않으면 인스턴스는 예외를 발생시키지 않으면 호출할 수 없는 메서드를 갖게 됩니다.

일부 소스가 추가하는 제약사항은 클래스가 데이터를 포함하지 않고 메서드만 포함할 수 있다는 것인데, 이것이 왜 필요한지 알 수 없습니다.그러나 실제로는 많은 유용한 믹스인에 데이터가 없으며 데이터가 없는 기본 클래스는 사용하기 더 쉽습니다.

로는 모든 를 '비교 연산자'에서만한 것입니다.<= ★★★★★★★★★★★★★★★★★」==:

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 class라는 용어는 해당 설계 패턴에서 사용되는 기본 클래스(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 메서드라는 용어를 명시적으로 사용하고 있습니다.

클래스가 다음과 같은 경우:

  • 를 실장하다__next__
  • 클래스에서 Iterator

그러면 학급은 수업을 받는다.__iter__ 믹스인 방식 무료입니다.

따라서 적어도 이 문서에서는 mixin은 여러 번 상속할 필요가 없으며 정의 1과 일관성이 있습니다.

물론 설명서는 서로 다른 점에서 모순될 수 있으며, 다른 중요한 Python 라이브러리는 설명서에서 다른 정의를 사용할 수 있습니다.

에서는 '이렇게 하다'라는 도 사용합니다.Set mixin 수업들은 하는 바가 있습니다.Set ★★★★★★★★★★★★★★★★★」Iterator믹스인.

기타 언어

  • Ruby: Programming Ruby 및 The Ruby Programming Language 등의 주요 참고서에서 언급되었듯이 믹스인을 위해 여러 번 상속할 필요는 없습니다.

  • C++: Avirtual=0는 순수 가상 방식입니다.

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

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

mixin은 mixin이라고 불리는 클래스에 대한 관례를 따르는 또 다른 python 클래스이기 때문에 여러 상속을 사용하는 절제된 방법이라고 생각합니다.

믹스인이라고 부르는 것을 규정하는 규약에 대한 저의 이해는 믹스인이란 것입니다.

  • 메서드는 추가하지만 인스턴스 변수는 추가하지 않습니다(클래스 상수는 OK).
  • 만 하다object ()

이렇게 하면 다중 상속의 복잡성이 제한되고 전체 다중 상속과 비교하여 검색해야 하는 위치를 제한하여 프로그램의 흐름을 추적하기가 상당히 쉬워집니다.루비 모듈과 비슷합니다.

인스턴스 변수(단일 상속에서 허용되는 것보다 더 유연한)를 추가할 경우 구성을 선택하는 경향이 있습니다.

그러고 보니 XYZMIXin이라는 인스턴스 변수가 있는 클래스를 본 적이 있습니다.

믹스인과 여러 상속을 구별하는 것은 무엇입니까?의미론적인 문제일까요?

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

특히 Python의 맥락에서 mixin은 서브클래스에 기능을 제공하지만 그 자체를 인스턴스화하는 것을 의도하지 않는 부모 클래스입니다.

"그것은 다중 상속일 뿐 실제로는 혼합되지 않습니다."라고 말하는 이유는 혼합과 혼동될 수 있는 클래스가 실제로 인스턴스화되어 사용될 수 있기 때문입니다. 즉, 이것은 의미론적인, 그리고 매우 현실적인 차이입니다.

다중 상속의 예

다음 예시는 매뉴얼에서 Ordered Counter 입니다.

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),)

은 두 모두에 .CounterOrderedDict collections★★★★★★ 。

다.Counter ★★★★★★★★★★★★★★★★★」OrderedDict인스턴스화 되어 스스로 사용되도록 되어 있습니다.그러나 둘 다 하위 분류함으로써 각 객체의 코드를 재사용하고 오더되는 카운터를 가질 수 있습니다.

이것은 코드를 재사용하는 강력한 방법이지만 문제가 될 수도 있습니다.오브젝트 중 하나에 버그가 있는 것으로 판명되었을 경우, 부주의하게 수정하면 서브클래스에 버그가 발생할 수 있습니다.

믹스인의 예

믹스인은 보통 Ordered Counter와 같은 공동 다중 상속에서 발생할 수 있는 잠재적 커플링 문제 없이 코드를 재사용할 수 있는 방법으로 홍보됩니다.믹스인을 사용하는 경우 데이터와 긴밀하게 결합되지 않은 기능을 사용합니다.

위의 예와 달리 믹스인은 단독으로 사용하기 위한 것이 아닙니다.새로운 기능 또는 다른 기능을 제공합니다.

예를 들어, 표준 라이브러리의 라이브러리에는 몇 가지 믹스인이 있습니다.

이러한 혼합 클래스를 사용하여 각 서버 유형의 포킹 및 스레드 버전을 만들 수 있습니다.예를 들어 스레딩UDPServer는 다음과 같이 작성됩니다.

class ThreadingUDPServer(ThreadingMixIn, UDPServer):
    pass

mix-in 클래스는 UDPServer에서 정의된 메서드보다 우선하기 때문에 우선됩니다.다양한 속성을 설정하면 기본 서버 메커니즘의 동작도 변경됩니다.

는 mixin 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)

MixIns가 무엇인지 지금까지의 답변이 매우 잘 정의되어 있었다고 생각합니다.단, 이들을 보다 잘 이해하기 위해서는 코드/실장 관점에서 추상 클래스인터페이스사용하는 MixIn을 비교하는 것이 도움이 될 수 있습니다.

1. 추상 클래스

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

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

2. 인터페이스

  • 인터페이스에 추상 메서드만 포함되어 있습니다(비추상 메서드 및 내부 상태 없음).

3. 믹스인

  • MixIn(인터페이스 등)에는 내부 상태(인스턴스 변수)가 포함되어 있지 않습니다.
  • MixIn에는 하나 이상의 비추출 메서드가 포함되어 있습니다(인터페이스와 달리 비추출 메서드를 포함할 수 있습니다).

이 "Python"으로 되어 있기 에 이는 규칙일 입니다.classes. 단, Abstract Class, InterfacesMixIns의 공통점은 그 자체가 존재하지 않아야 한다는 것, 즉 인스턴스화해서는 안 된다는 것입니다.

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

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

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

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

Scala에서는 여기서 설명한 바와 같이 mixin을 수행할 수 있지만 흥미로운 점은 mixin이 실제로 함께 '퓨전'되어 상속할 새로운 종류의 클래스를 만든다는 것입니다.기본적으로 여러 클래스/믹신에서 상속하는 것이 아니라 상속할 믹신의 모든 속성을 가진 새로운 종류의 클래스를 생성합니다.이는 Scala가 현재 다중 상속이 지원되지 않는 JVM을 기반으로 하기 때문에 의미가 있습니다(Java 8 현재).참고로 이 믹스인 클래스 타입은 스칼라에서 특성이라고 불리는 특별한 타입입니다.

클래스가 정의되어 있음을 시사합니다.클래스 NewClass는 FirstMixin을 SecondMixin과 ThirdMixin으로 확장합니다.

CPython 인터프리터도 같은(믹신 클래스 구성)지 모르겠지만, 놀랄 일은 아닙니다.또, C++의 배경으로부터, ABC나 믹스인에 상당하는 「인터페이스」라고는 말할 수 없습니다.이것은 같은 개념이지만, 사용이나 실장에서는 다릅니다.

새로운 Python 코드에 믹스인을 하는 것은 별로 어렵지 않은 방법(예를 들어 상속이 아닌 컴포지션 또는 자신의 클래스에 원숭이 패칭 방법)을 찾을 수 있다면 권장한다.

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

다중 상속 MRO를 Python에서 작동시키는 방법, 특히 super() 함수가 있지만 이는 super()를 사용하여 전체 클래스 계층을 수행해야 한다는 것을 의미하며 제어 흐름을 이해하는 것은 상당히 어렵습니다.

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

클래스를 만들고 , 를 정의할 수 .__ __ 하지만 그건 좀 고통스럽네요.몇 하고, 상속도 할 수 .UserDict.DictMixin: (예:)에)collections.DictMixin()py3k로 합니다.그러면 나머지 모든 사전 api가 자동으로 정의됩니다.

두 번째 예: GUI 툴킷 wxPython을 사용하면 여러 열(Windows 탐색기의 파일 표시 등)로 목록 컨트롤을 만들 수 있습니다.기본적으로는 이러한 목록은 매우 기본적입니다.ListCtrl에서 상속하여 적절한 믹스인을 추가하여 컬럼헤더를 클릭하여 특정 컬럼별로 목록을 정렬하는 기능 등의 추가 기능을 추가할 수 있습니다.

이것은 Python의 예는 아니지만 D 프로그래밍 언어에서 이 용어는 클래스와 거의 동일한 방식으로 사용되는 구조를 가리키기 위해 사용됩니다. 즉, 클래스에 더미를 추가하는 것입니다.

D(그건 그렇고 MI는 하지 않습니다)에서는 템플릿(통사적으로 인식되고 안전한 매크로를 생각하면 가까워집니다)을 스코프에 삽입함으로써 이루어집니다.이것에 의해, 클래스, 구조, 함수, 모듈등의 코드의 1 행이 임의의 수의 선언으로 확장됩니다.

OP는 C++에서의 mixin에 대해 들어본 적이 없다고 언급하고 있습니다.이는 C++에서는 curiously recurring template pattern(CRTP)이라고 불리고 있기 때문입니다.또한 @Ciro Santilli는 혼합은 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 개체를 만들 때 보호된 생성자가 컴파일 오류를 발생시키는 방법을 보여 주기 위해 예가 업데이트되었습니다.

mixin을 사용하면 클래스에 기능을 추가할 수 있습니다.즉, 원하는 클래스 내에 모듈을 포함시킴으로써 모듈에 정의된 메서드와 상호 작용할 수 있습니다.루비는 다중 상속을 지원하지 않지만 이를 위한 대안으로 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

방금 파이톤 믹스인을 사용하여 파이톤 밀터의 유닛 테스트를 실시했습니다.통상, 밀터는 MTA와 통신하기 때문에, 유닛의 테스트가 어려워집니다.테스트 믹스인은 MTA와 통신하는 메서드를 덮어쓰고 대신 테스트 케이스에 의해 구동되는 시뮬레이션 환경을 만듭니다.

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)

그런 다음 Test Milter를 Milter 어플리케이션 테스트 케이스에 사용합니다.

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

Ruby의 예는 다음과 같습니다.

믹스인을 수 있어요.Comparable 한 가지 를 정의해당 함수는요?"<=>(other)"을 제공합니다:in am am am am am am am am am am am am am am am am am am am ada.

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

은, 이 동작은, 이 동작에 의해서 행해집니다.<=>(other)을 사용법

"instance <=> other"한 경우 하고, 0이 같은 경우 을 반환하며, 0이 아닌 경우 0을 반환합니다.instance 크다other이 되면 이 넘습니다.other더 커요.

당신의 배경은 c#이라고 읽었습니다.따라서 의 믹스인 구현이 좋은 출발점이 될 수 있습니다.그물.

codeplex 프로젝트는 http://remix.codeplex.com/ 에서 확인하실 수 있습니다.

개요는 lang.net 심포지엄 링크를 참조하십시오.codeplex 페이지의 문서에는 아직 더 많은 정보가 있습니다.

스테판님

이 컨셉은 1973년 스티브 헤렐이 매사추세츠주 소머빌에 설립한 아이스크림 가게 스티브 아이스크림에서 유래한 것으로, 아이스크림의 기본 맛(바닐라, 초콜릿 등)에 믹스인(캔디, 케이크 등)을 섞었다.

Steve's Ice Cream에서 영감을 얻어 Lisp 객체 시스템 Flavors의 디자이너는 믹스인으로 알려진 다른 클래스와 플레이버로 알려진 대형 스탠드아론 클래스를 강화하도록 설계된 작은 도우미 클래스를 사용하여 처음으로 프로그래밍 언어로 개념을 포함시켰습니다.

즉, 혼합재사용 가능한 확장('배타적'이 아닌 '재이용 가능', '기반'이 아닌 '확장')이라는 개념입니다.

이 개념은 단일 또는 다중 상속 및 추상 또는 구체적 클래스의 개념과 직교합니다.혼합 클래스는 단일 또는 여러 상속에서 사용할 수 있으며 추상 또는 구체적인 클래스일 수 있습니다.혼합 클래스에는 불완전한 인터페이스가 있는 반면 추상 클래스에는 불완전한 구현이 있고 구체적인 클래스에는 완전한 구현이 있습니다.

의 Mix-In,'-ible를 들어, Python 표준 라이브러리에서 Mix-In, '-able', '-ble'은 Python을 ThreadingMixIn ★★★★★★★★★★★★★★★★★」ForkingMixIn모듈 클래스 및Hashable,Iterable,Callable,Awaitable,AsyncIterable , , , , 입니다.Reversible모듈 클래스입니다.

은 Python Python을 입니다.list ★★★★★★★★★★★★★★★★★」dict" " " 깅능이이능이이 。

import logging

class LoggingMixIn:
    def __setitem__(self, key, value):
        logging.info('Setting %r to %r', key, value)
        super().__setitem__(key, value)
    def __delitem__(self, key):
        logging.info('Deleting %r', key)
        super().__delitem__(key)

class LoggingList(LoggingMixIn, list):
    pass

class LoggingDict(LoggingMixIn, dict):
    pass
>>> logging.basicConfig(level=logging.INFO)
>>> l = LoggingList([False])
>>> d = LoggingDict({'a': False})
>>> l[0] = True
INFO:root:Setting 0 to True
>>> d['a'] = True
INFO:root:Setting 'a' to True
>>> del l[0]
INFO:root:Deleting 0
>>> del d['a']
INFO:root:Deleting 'a'

언급URL : https://stackoverflow.com/questions/533631/what-is-a-mixin-and-why-is-it-useful

반응형