Mixin vs kế thừa


Câu trả lời:


66

Một mixin thường được sử dụng với đa kế thừa. Vì vậy, theo nghĩa đó, không có sự khác biệt.

Chi tiết là một mixin hiếm khi hữu ích như một đối tượng độc lập.

Ví dụ: giả sử bạn có một mixin có tên "ColorAndDimension", bổ sung thuộc tính màu và chiều rộng và chiều cao.

Bây giờ, bạn có thể thêm ColorAndDimension vào lớp Shape, lớp Sprite, lớp Xe, v.v. Và tất cả chúng sẽ có cùng giao diện (ví dụ: get / setColor, get / setHeight / Width, v.v.)

Vì vậy, trong trường hợp chung, một sự kế thừa mixin IS. Nhưng bạn có thể tranh luận rằng đó là vấn đề về vai trò của lớp trong miền tổng thể như liệu một mixin có phải là một lớp "chính" hay đơn giản là một mixin.


Chỉnh sửa - chỉ để làm rõ.

Có, một mixin có thể được coi là, trong biệt ngữ hiện đại ngày nay, là một Giao diện với một Triển khai liên quan. Nó thực sự là đơn giản, cũ, đa kế thừa hàng ngày sử dụng một lớp đơn giản, cũ, hàng ngày. Nó chỉ là một ứng dụng cụ thể của MI. Hầu hết các ngôn ngữ không cung cấp trạng thái đặc biệt cho mixin; nó chỉ là một lớp được thiết kế để "trộn lẫn vào", thay vì được sử dụng độc lập.


29

Sự khác biệt giữa mixin và kế thừa là gì?

Kết hợp là một lớp cơ sở mà bạn có thể kế thừa để cung cấp chức năng bổ sung. Ví dụ về mã giả:

class Mixin:
    def complex_method(self):
        return complex_functionality(self)

Tên "trộn lẫn" cho biết nó được dùng để trộn với mã khác. Do đó, suy luận là bạn sẽ không tự khởi tạo lớp kết hợp. Đối tượng sau không có dữ liệu và không có ý nghĩa gì khi khởi tạo nó để gọi complex_method. (Bạn cũng có thể chỉ định nghĩa một hàm thay vì một lớp trong trường hợp đó.)

>>> obj = Mixin()

Thường thì hỗn hợp được sử dụng với các lớp cơ bản khác.

Do đó, mixin là một tập hợp con, hoặc trường hợp đặc biệt, của sự kế thừa.

Ưu điểm của việc sử dụng kết hợp trên kế thừa đơn là bạn có thể viết mã cho chức năng một lần và sau đó sử dụng cùng một chức năng trong nhiều lớp khác nhau. Điểm bất lợi là bạn có thể cần phải tìm kiếm chức năng đó ở những nơi khác chứ không phải nơi nó được sử dụng, vì vậy tốt hơn là bạn nên giảm thiểu nhược điểm đó bằng cách giữ nó gần đó.

Cá nhân tôi đã tìm thấy một sự kết hợp cần thiết để sử dụng thay vì kế thừa đơn lẻ trong đó chúng tôi đang lấy ra rất nhiều mã tương tự, nhưng các trường hợp thử nghiệm được khởi tạo dựa trên sự kế thừa của một trường hợp cơ sở và cách duy nhất để giữ mã gần hand (và trong cùng một mô-đun), không gây rối với các số phủ, là kế thừa từ đối tượng và để các trường hợp con kế thừa từ cả cơ sở trường hợp thử nghiệm phổ quát và cơ sở tùy chỉnh chỉ áp dụng cho chúng.

Các hỗn hợp so sánh và tương phản với các lớp cơ sở trừu tượng

Cả hai đều là một dạng của lớp cha không nhằm mục đích khởi tạo.

Một mixin cung cấp chức năng, nhưng không thể trực tiếp sử dụng nó. Người dùng được dự định sử dụng nó thông qua một lớp (con).

Một lớp cơ sở trừu tượng cung cấp một giao diện, nhưng không có chức năng sử dụng được. Người dùng nhằm tạo ra chức năng được gọi bởi giao diện.

class Abstraction(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def complex_method(self):
        return complex_functionality(self)

Tại đây, bạn bị ngăn không cho khởi tạo đối tượng này vì nó yêu cầu một lớp con để triển khai chức năng với một phương thức cụ thể (mặc dù bạn có thể truy cập chức năng bên trong từ super()):

>>> obj = Abstraction()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstraction with
abstract methods complex_method

Trong Python, một số lớp trong abcmô-đun là ví dụ về các lớp cha cung cấp chức năng thông qua kế thừa và các giao diện trừu tượng phải được thực thi bởi lớp con. Những ý tưởng này không loại trừ lẫn nhau.

Tóm lược

Nói một cách đơn giản, mix-in chỉ là một lớp cơ sở mà bạn không thể tự khởi tạo nó và thường được sử dụng như một lớp cơ sở thứ cấp trong đa kế thừa.


18

mix-in là một trường hợp cụ thể, bị hạn chế của (nhiều) kế thừa được sử dụng cho các mục đích thực hiện; một số ngôn ngữ (ví dụ: Ruby) hỗ trợ nó mà không hỗ trợ đa kế thừa tổng quát.


7

Mixin là một khái niệm trừu tượng và bất cứ thứ gì đáp ứng được yêu cầu của nó đều có thể được coi là mixin.

Đây là một định nghĩa từ Wikipedia.

Trong ngôn ngữ lập trình hướng đối tượng, mixin là một lớp chứa các phương thức để các lớp khác sử dụng mà không cần phải là lớp cha của các lớp khác đó. Cách các lớp khác đó có quyền truy cập vào các phương thức của mixin phụ thuộc vào ngôn ngữ. Mixin đôi khi được mô tả là được "bao gồm" hơn là "kế thừa".

Tóm lại, sự khác biệt chính so với kế thừa là mix-in KHÔNG cần phải có mối quan hệ "is-a" như trong kế thừa.

Từ quan điểm triển khai, bạn có thể nghĩ nó như một giao diện với các triển khai. Ví dụ, một lớp trừu tượng trong Java có thể được coi là một mixin nếu Java hỗ trợ đa kế thừa.


Tôi đang gặp khó khăn để hiểu câu in đậm. Có vẻ như "sự khác biệt (của B?) Từ A là nó (B?) Cần một cái gì đó giống như trong A". Bạn đang nói về sự khác biệt hay giống nhau?
RayLuo

@RayLuo Rất tiếc ... Tôi đã mắc một số lỗi đánh máy. Xin lỗi đã làm bạn bối rối. Mix-ins KHÔNG cần phải có một "là-một" mối quan hệ
Alex

3

"Mixin là một phần của một lớp theo nghĩa là nó được thiết kế để tạo ra các lớp hoặc mixin khác." -DDJ

Mixin là một lớp hoặc đoạn mã không nhằm mục đích sử dụng độc lập, nhưng thay vào đó bạn phải sử dụng nó bên trong một lớp khác. Có thể soạn nó như một trường / biến thành viên hoặc dưới dạng một đoạn mã. Tôi tiếp xúc nhiều nhất về sau. Nó tốt hơn một chút so với việc sao chép-dán mã bảng soạn sẵn.

Đây là một bài báo DDJ tuyệt vời giới thiệu chủ đề này.

SDK Half-Life 2 / "Nguồn" là một ví dụ tuyệt vời về hỗn hợp C ++. Trong môi trường đó, macro xác định các khối mã lớn có thể được thêm vào để tạo cho lớp một "hương vị" hoặc tính năng cụ thể.

Xem ví dụ về nguồn wiki: Tác giả một thực thể lôgic . Trong mã ví dụ, macro DECLARE_CLASS có thể được coi là một mixin. SDK nguồn sử dụng rộng rãi các kết hợp để chuẩn hóa mã truy cập dữ liệu và mô tả các hành vi cho các thực thể.


0

Với đa kế thừa, lớp mới có thể được tạo từ nhiều lớp cha. Bạn chỉ có thể gọi các phương thức được định nghĩa trong bất kỳ lớp cha nào.

Mặt khác, mixin là một lớp con trừu tượng có thể được sử dụng để chuyên biệt hóa hoạt động của nhiều lớp cha khác nhau. Mixin có thể gọi một phương thức (ví dụ sayHello(): String) mặc dù chúng không định nghĩa một phương thức như vậy.

mixin M {
    name: String
    defmethod greetings() { print sayHello() + " " + name}
}

Như bạn thấy, bạn có thể gọi sayHello()mặc dù nó không được định nghĩa ở bất kỳ đâu. Nếu bạn thêm mixin Mvào lớp C, thì Csẽ cung cấp sayHello()phương thức.


1
không chắc chắn về tính chính xác của tuyên bố đầu tiên của bạn - các lớp học có thể xác định phương pháp riêng của họ
EugeneMi

0

Tôi nghĩ điều quan trọng cần lưu ý, rằng mixin không ngụ ý kế thừa . Theo wikipedia, Mixin là:

Trong ngôn ngữ lập trình hướng đối tượng, mixin là một lớp chứa các phương thức để các lớp khác sử dụng mà không cần phải là lớp cha của các lớp khác đó. Cách các lớp khác đó có quyền truy cập vào các phương thức của mixin phụ thuộc vào ngôn ngữ. Mixin đôi khi được mô tả là được "bao gồm" hơn là "kế thừa".

Cụ thể, bằng một ngôn ngữ như perl, có thể thêm mixin bằng cách sử dụng mô-đun Trình xuất:

package Mixins;

use Exporter qw(import);
our @EXPORT_OK = qw(pity);

# assumes it will be mixed-in to a class with a _who_do_i_pity method
sub pity {
    my ($self) = @_;
    printf("I pity %s\n", $self->_who_do_i_pity('da foo'));
}

Có thể trộn lẫn vào bất kỳ mô-đun nào có chứa một hoặc nhiều (các) phương thức tại một thời điểm:

package MrT

use Mixins qw(pity);

sub new {
    return bless({}, shift);
}

sub _who_do_i_pity {
    return 'da foo!'
}

Sau đó, trong MrTmô-đun của bạn có thể được sử dụng như vậy:

use MrT;

MrT->new()->pity();

Tôi biết đó là một ví dụ vô lý, nhưng, nó đi đúng điểm ...


0

tl; dr

mixin và đa thừa kế có dạng giống nhau. Nhưng có ngữ nghĩa khác nhau: mixin có các lớp cơ bản cung cấp việc triển khai chức năng. Đối với kế thừa, các lớp cơ sở cung cấp giao diện và lớp con có phần thực hiện.

Nhưng dù sao, sáng tác được ưu tiên hơn mixin IMO

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.