Mixin vs warisan

Jawaban:

66

Mixin biasanya digunakan dengan multiple inheritance. Jadi, dalam pengertian itu, "tidak ada perbedaan".

Detailnya adalah bahwa mixin jarang berguna sebagai objek yang berdiri sendiri.

Misalnya, Anda memiliki mixin bernama "ColorAndDimension", yang menambahkan properti warna serta lebar dan tinggi.

Sekarang, Anda dapat menambahkan ColorAndDimension ke, katakanlah, kelas Bentuk, kelas Sprite, kelas Mobil, dll. Dan semuanya akan memiliki antarmuka yang sama (misalnya get / setColor, get / setHeight / Width, dll.)

Jadi, dalam kasus umum, warisan IS mixin. Tapi Anda bisa membantah bahwa ini adalah masalah peran kelas di domain keseluruhan, apakah mixin adalah kelas "primer" atau hanya sebuah mixin.


Edit - hanya untuk memperjelas.

Ya, mixin dapat dianggap, dalam istilah modern saat ini, Antarmuka dengan Implementasi terkait. Ini benar-benar hanya warisan ganda biasa, tua, sehari-hari menggunakan kelas biasa, tua, sehari-hari. Itu kebetulan merupakan aplikasi khusus MI. Kebanyakan bahasa tidak memberikan status khusus pada mixin; ini hanya kelas yang dirancang untuk "dicampur", bukan digunakan secara mandiri.

Will Hartung
sumber
29

Apa perbedaan antara mixin dan inheritance?

Sebuah campuran-in adalah kelas dasar Anda dapat mewarisi dari untuk menyediakan fungsionalitas tambahan. Contoh Pseudocode:

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

Nama "campuran" menunjukkan itu dimaksudkan untuk dicampur dengan kode lain. Dengan demikian, kesimpulannya adalah Anda tidak akan membuat instance kelas mix-in sendiri. Objek berikut tidak memiliki data, dan tidak masuk akal untuk membuat instance memanggil complex_method. (Anda mungkin juga hanya mendefinisikan fungsi daripada kelas dalam kasus itu.)

>>> obj = Mixin()

Seringkali campuran digunakan dengan kelas dasar lainnya.

Oleh karena itu mixin adalah subset, atau kasus khusus, dari pewarisan.

Keuntungan menggunakan campuran melalui satu warisan adalah Anda dapat menulis kode untuk fungsionalitas satu kali, dan kemudian menggunakan fungsionalitas yang sama di beberapa kelas yang berbeda. Kerugiannya adalah Anda mungkin perlu mencari fungsionalitas itu di tempat lain selain di tempat penggunaannya, jadi sebaiknya Anda mengurangi kerugian itu dengan membuatnya tetap dekat.

Saya pribadi telah menemukan campuran yang diperlukan untuk digunakan lebih dari satu warisan di mana kami menyatukan banyak kode yang serupa, tetapi kasus uji dibuat berdasarkan warisannya dari kasus dasar, dan satu-satunya cara untuk menjaga agar kode tetap dekat hand (dan dalam modul yang sama), tanpa mengotak-atik nomor cakupan, adalah mewarisi dari objek, dan memiliki kasus turunan yang diwarisi dari basis kasus uji universal dan basis kustom yang hanya berlaku untuk mereka.

Mixins dalam Perbandingan dan Kontras dengan Kelas Dasar Abstrak

Keduanya adalah bentuk kelas induk yang tidak dimaksudkan untuk dibuat instance-nya.

Sebuah mixin menyediakan fungsionalitas, tetapi tidak dapat langsung menggunakannya. Seorang pengguna dimaksudkan untuk menggunakannya melalui (sub) kelas.

Sebuah kelas dasar abstrak menyediakan antarmuka, tetapi tanpa fungsi yang dapat digunakan. Seorang pengguna dimaksudkan untuk membuat fungsionalitas yang dipanggil oleh antarmuka.

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

Di sini Anda dicegah membuat instance objek ini karena memerlukan subclass untuk mengimplementasikan fungsionalitas dengan metode konkret (meskipun Anda dapat mengakses fungsionalitas di dalamnya dari 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

Di Python, beberapa kelas dalam abcmodul adalah contoh kelas induk yang menyediakan fungsionalitas melalui pewarisan dan antarmuka abstrak yang harus diimplementasikan oleh subkelas. Ide-ide ini tidak eksklusif satu sama lain.

Ringkasan

Sederhananya, campuran hanyalah kelas dasar yang tidak akan Anda buat sendiri, dan biasanya digunakan sebagai kelas dasar sekunder dalam beberapa pewarisan.

Aaron Hall
sumber
18

campuran adalah kasus khusus, terbatas dari (banyak) warisan yang digunakan untuk tujuan implementasi; beberapa bahasa (misalnya Ruby) mendukungnya tanpa mendukung multiple inheritance secara umum.

Alex Martelli
sumber
7

Mixin adalah konsep abstrak dan apa pun yang memenuhi persyaratannya dapat dianggap sebagai mixin.

Berikut ini definisi dari Wikipedia.

Dalam bahasa pemrograman berorientasi objek, mixin adalah kelas yang berisi metode untuk digunakan oleh kelas lain tanpa harus menjadi kelas induk dari kelas lain tersebut. Bagaimana kelas-kelas lain itu mendapatkan akses ke metode mixin bergantung pada bahasanya. Mixin terkadang digambarkan sebagai "disertakan" daripada "diwariskan".

Singkatnya, perbedaan utama dari inheritance adalah bahwa mix-in TIDAK perlu memiliki hubungan "is-a" seperti di inheritance.

Dari sudut pandang implementasi, Anda dapat menganggapnya sebagai antarmuka dengan implementasi. Misalnya, kelas abstrak di Java dapat dianggap sebagai campuran jika Java mendukung beberapa pewarisan.

Alex
sumber
Saya kesulitan memahami kalimat yang dicetak tebal. Kedengarannya seperti "perbedaan (B?) Dari A adalah (B?) Memang membutuhkan sesuatu seperti di A". Apakah Anda berbicara tentang perbedaan atau kesamaan?
RayLuo
@RayLuo Ups ... Saya salah ketik. Maaf membuat Anda bingung. Mix-in TIDAK perlu memiliki hubungan "is-a"
Alex
3

"Mixin adalah bagian dari kelas dalam arti bahwa itu dimaksudkan untuk dikomposisikan dengan kelas atau mixin lain." -DDJ

Mixin adalah kelas atau fragmen kode yang tidak dimaksudkan untuk penggunaan mandiri, tetapi Anda seharusnya menggunakannya di dalam kelas lain. Entah menyusunnya sebagai bidang anggota / variabel atau sebagai segmen kode. Saya memiliki eksposur paling banyak ke nanti. Ini sedikit lebih baik daripada menyalin kode boilerplate.

Inilah artikel DDJ bagus yang memperkenalkan subjek tersebut.

Half-Life 2 / "Source" SDK adalah contoh yang bagus dari mixin C ++. Dalam lingkungan itu, makro menentukan blok kode yang cukup besar yang dapat ditambahkan untuk memberi kelas "rasa" atau fitur tertentu.

Lihat contoh wiki Sumber: Membuat Entitas Logis . Dalam kode contoh makro DECLARE_CLASS dapat dianggap sebagai mixin. Source SDK menggunakan mixin secara ekstensif untuk membakukan kode akses data dan menganggap perilaku entitas.

Karl the Pagan
sumber
0

Dengan multiple inheritance, kelas baru dapat disusun dari beberapa kelas super. Anda hanya dapat memanggil metode yang ditentukan di kelas super mana pun.

Di sisi lain, mixin adalah subkelas abstrak yang dapat digunakan untuk mengkhususkan diri pada perilaku berbagai kelas induk. Mixins dapat memanggil metode (misalnya sayHello(): String) meskipun mereka tidak mendefinisikan metode seperti itu.

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

Seperti yang Anda lihat, Anda dapat memanggil sayHello()meskipun tidak ditentukan di mana pun. Jika Anda menambahkan mixin Mke kelas C, Charus menyediakan sayHello()metode.

jk_
sumber
1
tidak yakin tentang kebenaran pernyataan pertama Anda - kelas dapat menentukan metode mereka sendiri
EugeneMi
0

Saya pikir penting untuk dicatat, bahwa mixin tidak menyiratkan warisan . Menurut wikipedia, Mixin adalah:

Dalam bahasa pemrograman berorientasi objek, mixin adalah kelas yang berisi metode untuk digunakan oleh kelas lain tanpa harus menjadi kelas induk dari kelas lain tersebut. Bagaimana kelas-kelas lain itu mendapatkan akses ke metode mixin bergantung pada bahasanya. Mixin terkadang digambarkan sebagai "disertakan" daripada "diwariskan".

Secara khusus, dalam bahasa seperti perl, mixin dapat ditambahkan menggunakan modul Exporter:

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'));
}

Yang dapat dicampur ke dalam modul apa pun yang berisi satu, atau lebih, metode pada satu waktu:

package MrT

use Mixins qw(pity);

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

sub _who_do_i_pity {
    return 'da foo!'
}

Kemudian MrTmodul Anda dapat digunakan sebagai berikut:

use MrT;

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

Saya tahu itu contoh yang tidak masuk akal, tetapi, itu menjelaskan maksudnya ...

Lucas
sumber
0

tl; dr

mixin dan multiple inheritance memiliki bentuk yang sama. Tetapi memiliki semantik yang berbeda: mixin memiliki kelas dasar yang menyediakan implementasi fungsi. Untuk warisan, kelas dasar menyediakan antarmuka dan subkelas memiliki implementasinya.

Tapi bagaimanapun, komposisi lebih disukai daripada mixin IMO

del bao
sumber