Mixin là gì và tại sao chúng lại hữu ích?

1009
TarkaDaal 2009-02-11 08:50.

Trong " Lập trình Python ", Mark Lutz đề cập đến "mixin". Tôi đến từ nền tảng C / C ++ / C # và tôi chưa từng nghe đến thuật ngữ này trước đây. Mixin là gì?

Đọc giữa các dòng của ví dụ này (mà tôi đã liên kết đến vì nó khá dài), tôi cho rằng đó là trường hợp sử dụng đa kế thừa để mở rộng một lớp thay vì phân lớp 'thích hợp'. Thê nay đung không?

Tại sao tôi muốn làm điều đó hơn là đặt chức năng mới vào một lớp con? Đối với vấn đề đó, tại sao cách tiếp cận mixin / đa kế thừa sẽ tốt hơn so với việc sử dụng thành phần?

Điều gì ngăn cách mixin với đa kế thừa? Nó chỉ là một vấn đề của ngữ nghĩa?

16 answers

747
Jason Baker 2009-02-14 11:15.

Mixin là một loại đa kế thừa đặc biệt. Có hai trường hợp chính khi mixin được sử dụng:

  1. Bạn muốn cung cấp nhiều tính năng tùy chọn cho một lớp.
  2. Bạn muốn sử dụng một tính năng cụ thể trong nhiều lớp khác nhau.

Đối với ví dụ về số một, hãy xem xét hệ thống yêu cầu và phản hồi của werkzeug . Tôi có thể tạo một đối tượng yêu cầu cũ đơn giản bằng cách nói:

from werkzeug import BaseRequest

class Request(BaseRequest):
    pass

Nếu tôi muốn thêm hỗ trợ tiêu đề chấp nhận, tôi sẽ làm điều đó

from werkzeug import BaseRequest, AcceptMixin

class Request(AcceptMixin, BaseRequest):
    pass

Nếu tôi muốn tạo một đối tượng yêu cầu hỗ trợ chấp nhận tiêu đề, thẻ etags, xác thực và hỗ trợ tác nhân người dùng, tôi có thể thực hiện điều này:

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

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

Sự khác biệt là nhỏ, nhưng trong các ví dụ trên, các lớp mixin không được tạo ra để đứng riêng. Trong đa kế thừa truyền thống, AuthenticationMixin(ví dụ) có thể sẽ giống hơn Authenticator. Đó là, lớp có thể sẽ được thiết kế để đứng riêng.

247
Randolpho 2009-02-11 09:00.

Đầu tiên, bạn cần lưu ý rằng mixin chỉ tồn tại trong các ngôn ngữ đa kế thừa. Bạn không thể thực hiện mixin trong Java hoặc C #.

Về cơ bản, mixin là một loại cơ sở độc lập cung cấp chức năng hạn chế và cộng hưởng đa hình cho một lớp con. Nếu bạn đang nghĩ về C #, hãy nghĩ về một giao diện mà bạn không cần phải thực thi vì nó đã được triển khai; bạn chỉ thừa hưởng từ nó và hưởng lợi từ chức năng của nó.

Mixin thường có phạm vi hẹp và không có nghĩa là được mở rộng.

[sửa - tại sao:]

Tôi cho rằng tôi nên giải quyết lý do tại sao, vì bạn đã hỏi. Lợi ích lớn là bạn không phải tự mình làm đi làm lại. Trong C #, nơi lớn nhất mà một mixin có thể được hưởng lợi có thể là từ mẫu vứt bỏ . Bất cứ khi nào bạn triển khai IDisposable, bạn hầu như luôn muốn làm theo cùng một mẫu, nhưng cuối cùng bạn phải viết đi viết lại cùng một đoạn mã cơ bản với các biến thể nhỏ. Nếu có một hỗn hợp Xử lý có thể mở rộng, bạn có thể tiết kiệm cho mình rất nhiều lần nhập thêm.

[chỉnh sửa 2 - để trả lời các câu hỏi khác của bạn]

Điều gì ngăn cách mixin với đa kế thừa? Nó chỉ là một vấn đề của ngữ nghĩa?

Đúng. Sự khác biệt giữa mixin và đa kế thừa tiêu chuẩn chỉ là vấn đề ngữ nghĩa; một lớp có đa kế thừa có thể sử dụng một mixin như một phần của đa kế thừa đó.

Điểm của mixin là tạo ra một kiểu có thể được "trộn lẫn" với bất kỳ kiểu nào khác thông qua kế thừa mà không ảnh hưởng đến kiểu kế thừa trong khi vẫn cung cấp một số chức năng có lợi cho kiểu đó.

Một lần nữa, hãy nghĩ về một giao diện đã được triển khai.

Cá nhân tôi không sử dụng mixin vì tôi chủ yếu phát triển bằng một ngôn ngữ không hỗ trợ chúng, vì vậy tôi đang gặp khó khăn khi tìm ra một ví dụ phù hợp sẽ chỉ cung cấp rằng "ahah!" thời điểm cho bạn. Nhưng tôi sẽ thử lại. Tôi sẽ sử dụng một ví dụ có sẵn - hầu hết các ngôn ngữ đã cung cấp tính năng này theo cách này hay cách khác - nhưng điều đó hy vọng sẽ giải thích cách mixin được tạo ra và sử dụng. Đây là:

Giả sử bạn có một kiểu mà bạn muốn có thể tuần tự hóa đến và từ XML. Bạn muốn kiểu cung cấp phương thức "ToXML" trả về một chuỗi chứa một phân đoạn XML với các giá trị dữ liệu của kiểu và "FromXML" cho phép kiểu này cấu trúc lại các giá trị dữ liệu của nó từ một phân đoạn XML trong một chuỗi. Một lần nữa, đây là một ví dụ có sẵn, vì vậy có thể bạn sử dụng một luồng tệp, hoặc một lớp XML Writer từ thư viện thời gian chạy của ngôn ngữ của bạn ... bất cứ điều gì. Vấn đề là bạn muốn tuần tự hóa đối tượng của mình thành XML và lấy lại một đối tượng mới từ XML.

Điểm quan trọng khác trong ví dụ này là bạn muốn làm điều này theo cách chung chung. Bạn không muốn phải triển khai phương thức "ToXML" và "FromXML" cho mọi kiểu mà bạn muốn tuần tự hóa, bạn muốn một số phương tiện chung để đảm bảo rằng kiểu của bạn sẽ thực hiện điều này và nó chỉ hoạt động. Bạn muốn sử dụng lại mã.

Nếu ngôn ngữ của bạn hỗ trợ nó, bạn có thể tạo mixin XmlSerializable để thực hiện công việc của bạn. Loại này sẽ triển khai các phương thức ToXML và FromXML. Nó sẽ, bằng cách sử dụng một số cơ chế không quan trọng đối với ví dụ, có khả năng thu thập tất cả dữ liệu cần thiết từ bất kỳ loại nào mà nó được trộn vào để xây dựng phân đoạn XML do ToXML trả về và nó sẽ có khả năng khôi phục dữ liệu đó khi FromXML được gọi là.

Và .. đó là nó. Để sử dụng nó, bạn sẽ có bất kỳ kiểu nào cần được tuần tự hóa sang XML kế thừa từ XmlSerializable. Bất cứ khi nào bạn cần tuần tự hóa hoặc giải mã hóa kiểu đó, bạn chỉ cần gọi ToXML hoặc FromXML. Trên thực tế, vì XmlSerializable là một kiểu chính thức và đa hình, bạn có thể hình dung ra một bộ tuần tự hóa tài liệu không biết gì về kiểu gốc của bạn, chỉ chấp nhận một mảng các kiểu XmlSerializable.

Bây giờ, hãy tưởng tượng sử dụng kịch bản này cho những việc khác, chẳng hạn như tạo một mixin đảm bảo rằng mọi lớp kết hợp nó trong nhật ký mọi lệnh gọi phương thức hoặc một mixin cung cấp giao dịch cho loại kết hợp nó. Danh sách có thể tiếp tục.

Nếu bạn chỉ nghĩ về mixin như một loại cơ bản nhỏ được thiết kế để thêm một lượng nhỏ chức năng vào một loại mà không ảnh hưởng đến loại đó, thì bạn là vàng.

Hy vọng. :)

Câu trả lời này nhằm mục đích giải thích các mixin bằng các ví dụ :

  • khép kín : ngắn gọn, không cần biết bất kỳ thư viện nào để hiểu ví dụ.

  • bằng Python , không phải bằng các ngôn ngữ khác.

    Có thể hiểu rằng đã có các ví dụ từ các ngôn ngữ khác như Ruby vì thuật ngữ này phổ biến hơn nhiều trong các ngôn ngữ đó, nhưng đây là một chuỗi Python .

Nó cũng sẽ xem xét câu hỏi gây tranh cãi:

Đa kế thừa có cần thiết hay không để xác định đặc điểm của một mixin?

Các định nghĩa

Tôi vẫn chưa thấy trích dẫn từ một nguồn "có thẩm quyền" nói rõ ràng mixin trong Python là gì.

Tôi đã thấy 2 định nghĩa có thể có của một mixin (nếu chúng được coi là khác với các khái niệm tương tự khác như các lớp cơ sở trừu tượng) và mọi người không hoàn toàn đồng ý về việc cái nào là đúng.

Sự đồng thuận có thể khác nhau giữa các ngôn ngữ khác nhau.

Định nghĩa 1: không có đa kế thừa

Mixin là một lớp mà một số phương thức của lớp sử dụng một phương thức không được định nghĩa trong lớp.

Do đó, lớp không có nghĩa là được khởi tạo, mà được dùng như một lớp cơ sở. Nếu không, instance sẽ có các phương thức không thể được gọi nếu không đưa ra một ngoại lệ.

Một hạn chế mà một số nguồn thêm vào là lớp có thể không chứa dữ liệu, chỉ có các phương thức, nhưng tôi không hiểu tại sao điều này lại cần thiết. Tuy nhiên, trong thực tế, nhiều mixin hữu ích không có bất kỳ dữ liệu nào và các lớp cơ sở không có dữ liệu sẽ dễ sử dụng hơn.

Một ví dụ cổ điển là việc triển khai tất cả các toán tử so sánh chỉ từ <===:

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 

Ví dụ cụ thể này có thể đạt được thông qua trình functools.total_ordering()trang trí, nhưng trò chơi ở đây là phát minh lại bánh xe:

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)

Định nghĩa 2: đa kế thừa

Mixin là một mẫu thiết kế trong đó một số phương thức của lớp cơ sở sử dụng phương thức mà nó không định nghĩa và phương thức đó được thực hiện bởi một lớp cơ sở khác , không phải bởi phương thức dẫn xuất như trong Định nghĩa 1.

Thuật ngữ lớp mixin đề cập đến các lớp cơ sở được dự định sử dụng trong mẫu thiết kế đó (CẦN LÀM những người sử dụng phương pháp hoặc những người triển khai nó?)

Không dễ dàng để quyết định xem một lớp nhất định có phải là một mixin hay không: phương thức có thể chỉ được triển khai trên lớp dẫn xuất, trong trường hợp đó chúng ta quay lại Định nghĩa 1. Bạn phải xem xét ý định của tác giả.

Mô hình này rất thú vị vì có thể kết hợp lại các chức năng với các lựa chọn khác nhau của các lớp cơ sở:

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

Số lần xuất hiện trong Python có thẩm quyền

Tại documentatiton chính thức cho collection.abc , tài liệu sử dụng thuật ngữ Phương pháp Mixin một cách rõ ràng .

Nó nói rằng nếu một lớp:

  • dụng cụ __next__
  • kế thừa từ một lớp duy nhất Iterator

sau đó lớp học sẽ nhận được một __iter__ phương thức mixin miễn phí.

Do đó, ít nhất về điểm này của tài liệu, mixin không yêu cầu đa kế thừa và nhất quán với Định nghĩa 1.

Tất nhiên, tài liệu có thể mâu thuẫn ở các điểm khác nhau và các thư viện Python quan trọng khác có thể đang sử dụng định nghĩa khác trong tài liệu của họ.

Trang này cũng sử dụng thuật ngữ này Set mixin, gợi ý rõ ràng rằng các lớp thích SetIteratorcó thể được gọi là các lớp Mixin.

Trong các ngôn ngữ khác

  • Ruby: Rõ ràng là không yêu cầu đa kế thừa cho mixin, như đã đề cập trong các sách tham khảo lớn như Lập trình Ruby và Ngôn ngữ lập trình Ruby

  • C ++: Một virtualphương thức được thiết lập =0là một phương thức ảo thuần túy.

    Định nghĩa 1 trùng với định nghĩa của một lớp trừu tượng (một lớp có một phương thức ảo thuần túy). Lớp đó không thể được khởi tạo.

    Định nghĩa 2 có thể với kế thừa ảo: Kế thừa nhiều từ hai lớp dẫn xuất

41
Hamish Downer 2013-07-06 04:26.

Tôi nghĩ về chúng như một cách kỷ luật để sử dụng đa kế thừa - bởi vì cuối cùng một mixin chỉ là một lớp python khác (có thể) tuân theo các quy ước về các lớp được gọi là mixin.

Sự hiểu biết của tôi về các quy ước chi phối thứ mà bạn sẽ gọi là Mixin là Mixin:

  • thêm các phương thức nhưng không thêm các biến thể hiện (các hằng số lớp là OK)
  • chỉ kế thừa từ object(bằng Python)

Bằng cách đó, nó hạn chế sự phức tạp tiềm ẩn của đa kế thừa và giúp bạn dễ dàng theo dõi luồng chương trình của mình một cách hợp lý bằng cách giới hạn nơi bạn phải xem (so với đa kế thừa đầy đủ). Chúng tương tự như các mô-đun ruby .

Nếu tôi muốn thêm các biến cá thể (với tính linh hoạt hơn mức cho phép của kế thừa đơn lẻ) thì tôi có xu hướng sử dụng thành phần.

Phải nói rằng, tôi đã thấy các lớp được gọi là XYZMixin có các biến cá thể.

31
Aaron Hall 2016-03-26 05:05.

Điều gì ngăn cách mixin với đa kế thừa? Nó chỉ là một vấn đề của ngữ nghĩa?

Mixin là một dạng đa kế thừa hạn chế. Trong một số ngôn ngữ, cơ chế thêm mixin vào một lớp hơi khác (về cú pháp) so với cơ chế kế thừa.

Đặc biệt, trong ngữ cảnh của Python, mixin là một lớp cha cung cấp chức năng cho các lớp con nhưng không nhằm mục đích khởi tạo chính nó.

Điều có thể khiến bạn nói, "đó chỉ là đa kế thừa, không thực sự là một mixin" là nếu lớp có thể bị nhầm lẫn với một mixin thực sự có thể được khởi tạo và sử dụng - vì vậy thực sự nó là một sự khác biệt về ngữ nghĩa và rất thực tế.

Ví dụ về thừa kế nhiều

Ví dụ này, từ tài liệu , là một 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),)

Nó phân lớp cả mô-đun CounterOrderedDicttừ collectionsmô-đun.

Cả hai CounterOrderedDictđều nhằm mục đích khởi tạo và sử dụng riêng. Tuy nhiên, bằng cách phân lớp cả hai, chúng ta có thể có một bộ đếm được sắp xếp và sử dụng lại mã trong mỗi đối tượng.

Đây là một cách hiệu quả để sử dụng lại mã, nhưng nó cũng có thể có vấn đề. Nếu hóa ra có lỗi ở một trong các đối tượng, việc sửa nó mà không cẩn thận có thể tạo ra lỗi trong lớp con.

Ví dụ về Mixin

Mixin thường được quảng cáo như một cách để sử dụng lại mã mà không có các vấn đề về khớp nối tiềm ẩn mà đa kế thừa hợp tác, như OrderedCounter, có thể mắc phải. Khi bạn sử dụng mixin, bạn sử dụng chức năng không được kết hợp chặt chẽ với dữ liệu.

Không giống như ví dụ trên, mixin không được sử dụng cho riêng nó. Nó cung cấp chức năng mới hoặc khác.

Ví dụ, thư viện chuẩn có một vài mixin trong socketserverthư viện .

Phiên bản phân nhánh và phân luồng của từng loại máy chủ có thể được tạo bằng cách sử dụng các lớp kết hợp này. Ví dụ, ThreadingUDPServer được tạo như sau:

class ThreadingUDPServer(ThreadingMixIn, UDPServer):
    pass

Lớp trộn vào đầu tiên, vì nó ghi đè một phương thức được định nghĩa trong UDPServer. Việc đặt các thuộc tính khác nhau cũng thay đổi hoạt động của cơ chế máy chủ bên dưới.

Trong trường hợp này, các phương thức mixin ghi đè các phương thức trong UDPServerđịnh nghĩa đối tượng để cho phép đồng thời.

Phương thức được ghi đè dường như là process_requestvà nó cũng cung cấp một phương thức khác process_request_thread,. Đây là từ mã nguồn :

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

Một ví dụ có sẵn

Đây là một mixin chủ yếu dành cho mục đích trình diễn - hầu hết các đối tượng sẽ phát triển ngoài tính hữu ích của bản đại diện này:

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

và cách sử dụng sẽ là:

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__()

Và cách sử dụng:

>>> f1 = Foo('bar')
>>> f2 = Foo()
>>> f1
Foo(foo='bar')
>>> f2
Foo(foo=None)
30
lakesh 2012-06-13 19:06.

Mixins là một khái niệm trong Lập trình, trong đó lớp cung cấp các chức năng nhưng nó không được sử dụng để khởi tạo. Mục đích chính của Mixin là cung cấp các chức năng độc lập và sẽ tốt nhất nếu bản thân các mixin không có sự kế thừa với các mixin khác và cũng tránh trạng thái. Trong các ngôn ngữ như Ruby, có một số hỗ trợ ngôn ngữ trực tiếp nhưng đối với Python thì không. Tuy nhiên, bạn có thể sử dụng kế thừa đa lớp để thực thi chức năng được cung cấp trong Python.

Tôi đã xem video này http://www.youtube.com/watch?v=v_uKI2NOLEMđể hiểu những kiến ​​thức cơ bản về mixin. Nó khá hữu ích cho người mới bắt đầu để hiểu những điều cơ bản về mixin và cách chúng hoạt động và những vấn đề bạn có thể gặp phải khi triển khai chúng.

Wikipedia vẫn là tốt nhất: http://en.wikipedia.org/wiki/Mixin

11
SilentDirge 2014-12-26 19:54.

Tôi nghĩ rằng đã có một số giải thích tốt ở đây nhưng tôi muốn cung cấp một góc nhìn khác.

Trong Scala, bạn có thể làm các mixin như đã được mô tả ở đây nhưng điều rất thú vị là các mixin thực sự được 'hợp nhất' với nhau để tạo ra một loại lớp mới để kế thừa. Về bản chất, bạn không kế thừa từ nhiều lớp / mixin, mà là tạo ra một loại lớp mới với tất cả các thuộc tính của mixin để kế thừa. Điều này có ý nghĩa vì Scala dựa trên JVM, nơi đa kế thừa hiện không được hỗ trợ (kể từ Java 8). Nhân tiện, loại lớp mixin này là một loại đặc biệt được gọi là Đặc điểm trong Scala.

Nó được gợi ý theo cách định nghĩa một lớp: lớp NewClass mở rộng FirstMixin với SecondMixin với ThirdMixin ...

Tôi không chắc liệu trình thông dịch CPython có làm như vậy không (thành phần lớp mixin) nhưng tôi sẽ không ngạc nhiên. Ngoài ra, đến từ nền tảng C ++, tôi sẽ không gọi ABC hoặc 'giao diện' tương đương với một mixin - đó là một khái niệm tương tự nhưng khác nhau về cách sử dụng và triển khai.

9
bobince 2009-02-11 09:21.

Tôi khuyên bạn không nên trộn lẫn trong mã Python mới, nếu bạn có thể tìm thấy bất kỳ cách nào khác xung quanh nó (chẳng hạn như thành phần-thay vì kế thừa hoặc chỉ các phương thức vá lỗi khỉ vào các lớp của riêng bạn). cố gắng.

Trong các lớp kiểu cũ, bạn có thể sử dụng mix-in như một cách để lấy một vài phương thức từ một lớp khác. Nhưng trong thế giới kiểu mới, mọi thứ, ngay cả sự pha trộn, đều kế thừa từ đó object. Điều đó có nghĩa là bất kỳ việc sử dụng đa kế thừa nào cũng đều gây ra các vấn đề MRO .

Có nhiều cách để làm cho MRO đa kế thừa hoạt động trong Python, đáng chú ý nhất là hàm super (), nhưng nó có nghĩa là bạn phải thực hiện phân cấp toàn bộ lớp của mình bằng cách sử dụng super () và việc hiểu luồng điều khiển sẽ khó hơn đáng kể.

9
John Fouhy 2009-02-11 11:27.

Có lẽ một vài ví dụ sẽ hữu ích.

Nếu bạn đang xây dựng một lớp và bạn muốn nó hoạt động như một từ điển, bạn có thể xác định tất cả các __ __phương thức khác nhau cần thiết. Nhưng đó là một chút đau đớn. Thay vào đó, bạn có thể chỉ cần xác định một vài và kế thừa (ngoài bất kỳ kế thừa nào khác) từ UserDict.DictMixin(được chuyển đến collections.DictMixintrong py3k). Điều này sẽ có tác dụng tự động xác định tất cả các phần còn lại của api từ điển.

Ví dụ thứ hai: bộ công cụ GUI wxPython cho phép bạn tạo các điều khiển danh sách với nhiều cột (chẳng hạn như hiển thị tệp trong Windows Explorer). Theo mặc định, các danh sách này khá cơ bản. Bạn có thể thêm chức năng bổ sung, chẳng hạn như khả năng sắp xếp danh sách theo một cột cụ thể bằng cách nhấp vào tiêu đề cột, bằng cách kế thừa từ ListCtrl và thêm các mixin thích hợp.

9
BCS 2009-02-18 22:00.

Nó không phải là một ví dụ Python nhưng trong ngôn ngữ lập trình D , thuật ngữ mixinnày được sử dụng để chỉ một cấu trúc được sử dụng theo cùng một cách; thêm một đống nội dung vào một lớp học.

Trong D (theo cách này không thực hiện MI), điều này được thực hiện bằng cách chèn một mẫu (nghĩ rằng các macro nhận biết cú pháp và an toàn và bạn sẽ ở gần) vào một phạm vi. Điều này cho phép một dòng mã trong một lớp, cấu trúc, hàm, mô-đun hoặc bất cứ thứ gì có thể mở rộng đến bất kỳ số lượng khai báo nào.

9
Tomasz Bartkowiak 2020-01-16 03:51.

Tôi nghĩ rằng các phản hồi trước đây đã xác định rất rõ MixIns là gì . Tuy nhiên, để hiểu rõ hơn về chúng, có thể hữu ích khi so sánh MixIns với các LớpGiao diện Tóm tắt từ góc độ mã / triển khai:

1. Lớp trừu tượng

  • Lớp cần chứa một hoặc nhiều phương thức trừu tượng

  • Lớp trừu tượng có thể chứa trạng thái (biến thể hiện) và các phương thức không trừu tượng

2. Giao diện

  • Giao diện chứa phương pháp trừu tượng chỉ (không có phương pháp phi trừu tượng và không có trạng thái nội bộ)

3. MixIns

  • MixIns (như Giao diện) không chứa trạng thái bên trong (biến phiên bản)
  • MixIns chứa một hoặc nhiều phương thức không trừu tượng (chúng có thể chứa các phương thức không trừu tượng không giống như các giao diện)

Trong ví dụ Python, đây chỉ là những quy ước, vì tất cả những điều trên được định nghĩa là classes. Tuy nhiên, đặc điểm chung của cả lớp Abstract Class, InterfacesMixIns là chúng không nên tự tồn tại, tức là không nên khởi tạo.

7
bigdata2 2016-12-06 20:30.

OP đã đề cập rằng anh ấy / cô ấy chưa bao giờ nghe nói về mixin trong C ++, có lẽ đó là vì chúng được gọi là Mẫu khuôn mẫu lặp lại kỳ lạ (CRTP) trong C ++. Ngoài ra, @Ciro Santilli đã đề cập rằng mixin được triển khai thông qua lớp cơ sở trừu tượng trong C ++. Mặc dù lớp cơ sở trừu tượng có thể được sử dụng để triển khai mixin, nhưng đó là một quá mức cần thiết vì chức năng của hàm ảo tại thời điểm chạy có thể đạt được bằng cách sử dụng mẫu tại thời điểm biên dịch mà không cần tra cứu bảng ảo tại thời điểm chạy.

Mẫu CRTP được mô tả chi tiết tại đây

Tôi đã chuyển đổi ví dụ python trong câu trả lời của @Ciro Santilli thành C ++ bằng cách sử dụng lớp mẫu bên dưới:

    #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;
}

CHỈNH SỬA: Đã thêm phương thức khởi tạo được bảo vệ trong Comp CompareMixin để nó chỉ có thể được kế thừa và không được khởi tạo. Đã cập nhật ví dụ để hiển thị cách phương thức khởi tạo được bảo vệ sẽ gây ra lỗi biên dịch khi một đối tượng của CompermanentMixin được tạo.

6
Georg Schölly 2009-02-11 09:08.

Có thể một ví dụ từ ruby ​​có thể giúp:

Bạn có thể bao gồm mixin Comparablevà xác định một chức năng "<=>(other)", mixin cung cấp tất cả các chức năng đó:

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

Nó thực hiện điều này bằng cách gọi <=>(other)và trả lại kết quả phù hợp.

"instance <=> other"trả về 0 nếu cả hai đối tượng bằng nhau, nhỏ hơn 0 nếu instancelớn hơn othervà lớn hơn 0 nếu otherlớn hơn.

6
Akash Soti 2012-08-01 01:49.

mixin cung cấp một cách để thêm chức năng trong một lớp, tức là bạn có thể tương tác với các phương thức được xác định trong một mô-đun bằng cách đưa mô-đun vào bên trong lớp mong muốn. Mặc dù ruby ​​không hỗ trợ đa kế thừa nhưng cung cấp mixin như một giải pháp thay thế để đạt được điều đó.

đây là một ví dụ giải thích cách đạt được đa kế thừa bằng cách sử dụng 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
6
Stuart Gathman 2013-03-13 11:22.

Tôi vừa sử dụng một hỗn hợp python để triển khai thử nghiệm đơn vị cho các milimet trăn. Thông thường, milter nói chuyện với MTA, khiến việc kiểm tra đơn vị trở nên khó khăn. Thử nghiệm mixin ghi đè các phương pháp nói chuyện với MTA và thay vào đó tạo ra một môi trường mô phỏng được điều khiển bởi các trường hợp thử nghiệm.

Vì vậy, bạn sử dụng một ứng dụng milter chưa được sửa đổi, như spfmilter và mixin TestBase, như thế này:

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)

Sau đó, sử dụng TestMilter trong các trường hợp thử nghiệm cho ứng dụng nhỏ hơn:

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='[email protected]')
  self.assertEqual(rc,Milter.CONTINUE)
  milter.close()

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

3
Stefan Papp 2011-03-24 00:16.

Tôi đọc rằng bạn có nền tảng ac #. Vì vậy, một điểm khởi đầu tốt có thể là triển khai mixin cho .NET.

Bạn có thể muốn xem dự án codeplex tại http://remix.codeplex.com/

Xem liên kết Hội nghị chuyên đề lang.net để có cái nhìn tổng quan. Vẫn còn nhiều hơn nữa về tài liệu trên trang codeplex.

liên quan đến Stefan

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Tận dụng lợi thế của việc bán hàng nhân Ngày của Cha này

Tận dụng lợi thế của việc bán hàng nhân Ngày của Cha này

Màn hình Samsung Galaxy S9 Plus. Chủ nhật này là Ngày của Cha⁠ — trong trường hợp nó khiến bạn suy nghĩ — và thay vì mua cho anh ấy một chiếc cà vạt trong năm nay, có lẽ đã đến lúc bạn mua cho anh ấy thứ mà anh ấy sẽ thực sự sử dụng.

Assassin's Creed Snuck Into Monster Hunter: World Last Night

Assassin's Creed Snuck Into Monster Hunter: World Last Night

Monster Hunter: World yêu thích các sự kiện chéo. Dù có nghĩa là hóa trang thành Dante của Devil May Cry, giả dạng Horizon: Zero Dawn's Aloy, hay chiến đấu với quái vật Final Fantasy, các nhiệm vụ sự kiện khác nhau của Thế giới được nâng cấp tự do so với các trò chơi khác.

Ava DuVernay Có Quà Tặng Ngày Của Mẹ cho Tất Cả Chúng Ta: Nếp Nhăn Thời Gian Sẽ Được Viết Lại Vào Cuối Tuần Ngày Của Mẹ!

Ava DuVernay Có Quà Tặng Ngày Của Mẹ cho Tất Cả Chúng Ta: Nếp Nhăn Thời Gian Sẽ Được Viết Lại Vào Cuối Tuần Ngày Của Mẹ!

Storm Reid, Oprah Winfrey, Mindy Kaling, Reese Witherspoon và Ava DuVernay tại buổi chiếu đặc biệt của A Wrinkle in Time tại Nhà hát Walter Reade ở Thành phố New York vào ngày 7 tháng 3 năm 2018 “Ava rất mong được nói chuyện với bạn,” một trong những người của Array dư luận viên nói qua điện thoại. (Array là tập thể phân phối, nghệ thuật và vận động chính sách của Ava DuVernay tập trung vào các bộ phim của người da màu và phụ nữ.

Nhiệm vụ bất khả thi 5 sẽ khôi phục niềm tin của bạn trong phim hành động Tentpole

Nhiệm vụ bất khả thi 5 sẽ khôi phục niềm tin của bạn trong phim hành động Tentpole

Mission Impossible: Rogue Nation bắt đầu ở một cấp độ khác. Theo nghĩa đen.

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

McCain, người đang làm việc cho một album mới, lần đầu tiên bước vào vòng kết nối vào tối thứ Sáu ở Nashville

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Tôi viết như thế nào

Tôi viết như thế nào

Đối với tôi, mọi thứ là về dòng đầu tiên đó và nó sẽ đưa bạn đến đâu. Một số nhà văn bị điều khiển bởi cốt truyện, sự sắp xếp tinh tế của các quân cờ, trong khi những người khác bị lôi cuốn bởi một nhân vật và khả năng thực hiện một cuộc hành trình với một người bạn hư cấu mới.

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Language