Masukkan Password
57 Mixins in Dart | Dart mixins | Dart Tutorial #57
Transcript ini membahas Mixin di Dart, dan menurut saya ini salah satu konsep OOP Dart yang paling penting untuk dipahami karena sangat sering muncul di Flutter.
Ada beberapa bagian transcript yang penyampaiannya kurang tepat atau merupakan penyederhanaan. Jadi saya akan menjelaskan konsepnya dari dasar, lalu membedakan extends, implements, dan with, kemudian membedah contoh mobil, dan terakhir menjelaskan on.
1. Apa itu Mixin?
Secara sederhana:
Mixin adalah kumpulan kemampuan (behavior/method/property) yang bisa “ditempelkan” ke sebuah class tanpa menggunakan inheritance melalui
extends.
Bayangkan kita punya beberapa kemampuan:
- bisa berenang
- bisa terbang
- bisa berbicara
- bisa berjalan
Kemampuan tersebut bisa kita buat sebagai mixin.
mixin CanSwim {
void swim() {
print("Sedang berenang");
}
}
Kemudian kita bisa menempelkan kemampuan itu ke class:
class Duck with CanSwim {
}
Sekarang:
final duck = Duck();
duck.swim();
Output:
Sedang berenang
Perhatikan:
class Duck with CanSwim
bukan:
class Duck extends CanSwim
Inilah salah satu inti pembahasan video.
2. Kenapa tidak menggunakan extends saja?
Karena extends mempunyai hubungan inheritance / IS-A.
Misalnya:
class Animal {
void eat() {
print("Animal eating");
}
}
class Cat extends Animal {
}
Artinya:
CatadalahAnimal.
Secara konsep:
Animal
↑
|
Cat
Sedangkan mixin lebih cocok untuk mengatakan:
“Class ini memiliki kemampuan X.”
Contohnya:
mixin CanSwim {
void swim() {
print("Swimming");
}
}
class Duck with CanSwim {
}
Artinya bukan:
Duck adalah CanSwim.
Tetapi:
Duck memiliki kemampuan untuk berenang.
Jadi:
extends → hubungan "IS-A"
with → menambahkan "ABILITY/BEHAVIOR"
Ini perbedaan mental model yang sangat penting.
3. Mixin berbeda dengan class biasa
Transcript mengatakan mixin mirip dengan class. Itu benar dalam beberapa hal.
Mixin bisa memiliki:
- instance variable
- static variable
- concrete method
- abstract method
- static method
- getter/setter
- dan anggota lainnya sesuai aturan Dart.
Tetapi mixin bukan class biasa yang bisa dibuat object-nya.
Misalnya:
mixin CanSwim {
void swim() {
print("Swimming");
}
}
Kita tidak bisa:
final x = CanSwim();
❌ Tidak boleh.
Karena CanSwim adalah mixin.
Kita harus menggunakannya melalui class:
class Duck with CanSwim {
}
final duck = Duck();
duck.swim();
4. Cara membuat mixin
Ada dua hal dalam transcript yang perlu diluruskan.
Cara modern dan jelas: menggunakan keyword mixin
mixin CanSwim {
void swim() {
print("Swimming");
}
}
Kemudian:
class Duck with CanSwim {
}
Selesai.
5. Mixin bisa memiliki variable
Contohnya:
mixin PersonInfo {
String name = "Budi";
void showName() {
print(name);
}
}
Kemudian:
class Student with PersonInfo {
}
Kita bisa:
final student = Student();
print(student.name);
student.showName();
Output:
Budi
Budi
Jadi property dari mixin menjadi bagian dari object class yang menggunakan mixin tersebut.
Secara sederhana:
PersonInfo
|
| with
↓
Student
|
├── name
└── showName()
6. Kenapa kita tidak bisa membuat object mixin?
Karena mixin bukan sesuatu yang berdiri sendiri.
Mixin lebih seperti kotak berisi kemampuan yang akan disisipkan ke class lain.
Misalnya:
mixin Flyable {
void fly() {
print("Flying");
}
}
Flyable sendiri bukan “makhluk” yang harus dibuat object.
Dia hanya menyediakan kemampuan:
Flyable
└── fly()
Kemudian:
class Bird with Flyable {
}
Sekarang Bird mendapatkan kemampuan tersebut.
7. Apa fungsi keyword with?
Ini bagian paling penting.
class Duck with CanSwim {
}
with berarti:
Gunakan mixin
CanSwimpada classDuck.
Setelah itu method/property dari mixin dapat digunakan oleh object Duck.
Contoh:
mixin CanSwim {
void swim() {
print("Duck is swimming");
}
}
class Duck with CanSwim {
}
Kemudian:
final duck = Duck();
duck.swim();
Output:
Duck is swimming
8. extends, implements, dan with
Ini tiga keyword yang sangat sering membingungkan pemula.
extends
Untuk inheritance.
class Animal {
void eat() {
print("Eating");
}
}
class Cat extends Animal {
}
Cat mendapatkan implementasi eat() dari Animal.
implements
Untuk memenuhi contract/interface.
abstract class Animal {
void eat();
}
class Cat implements Animal {
@override
void eat() {
print("Cat eating");
}
}
Cat tidak otomatis mendapatkan implementasi dari Animal.
Cat harus menyediakan implementasinya sendiri.
with
Untuk menggunakan mixin.
mixin CanSwim {
void swim() {
print("Swimming");
}
}
class Duck with CanSwim {
}
Duck mendapatkan implementasi swim() dari mixin.
Ringkasnya
| Keyword | Fungsi utama |
|---|---|
extends | inheritance |
implements | memenuhi contract/interface |
with | menggunakan mixin |
on | membatasi mixin agar hanya bisa digunakan pada tipe tertentu |
Mental model:
extends
↓
"A adalah B"
implements
↓
"A memenuhi contract B"
with
↓
"A mendapatkan kemampuan dari B"
9. Mixin bisa digunakan lebih dari satu
Ini salah satu kelebihan terbesar mixin.
Misalnya:
mixin CanSwim {
void swim() {
print("Swimming");
}
}
mixin CanFly {
void fly() {
print("Flying");
}
}
Kita bisa:
class Duck with CanSwim, CanFly {
}
Sekarang:
final duck = Duck();
duck.swim();
duck.fly();
Output:
Swimming
Flying
Jadi satu class dapat menggunakan beberapa mixin.
Secara visual:
CanSwim ───────┐
│
CanFly ────────┼──→ Duck
│
└──→ swim() + fly()
10. Mixin vs multiple inheritance
Di Dart kita tidak bisa melakukan:
class C extends A, B {
}
❌ Tidak diperbolehkan.
Karena Dart hanya mempunyai satu superclass langsung.
Tetapi Dart menyediakan mixin:
class C extends A with MixinB, MixinC {
}
Jadi kita bisa mendapatkan behavior dari beberapa sumber tanpa melakukan multiple inheritance.
11. Contoh paling penting dari transcript: Car
Sekarang kita masuk ke contoh mobil karena ini sebenarnya alasan kenapa mixin dibuat.
Kita mempunyai tiga jenis mobil:
PetrolCar
ElectricCar
HybridCar
PetrolCar
Mobil bensin memiliki:
feature()
petrolEngine()
needsPetrol()
ElectricCar
Mobil listrik memiliki:
feature()
electricMotor()
needsBattery()
HybridCar
Hybrid mempunyai:
feature()
petrolEngine()
needsPetrol()
electricMotor()
needsBattery()
Masalahnya:
feature()
diulang di tiga class.
Itu duplication.
12. Solusi pertama: inheritance
Kita bisa membuat:
abstract class Car {
void feature() {
print("Car feature");
}
}
Kemudian:
class PetrolCar extends Car {
}
class ElectricCar extends Car {
}
class HybridCar extends Car {
}
Sekarang ketiganya mendapatkan:
feature()
Bagus.
13. Tetapi muncul masalah baru
Kita ingin petrolEngine() dan needsPetrol() hanya dimiliki oleh:
- PetrolCar
- HybridCar
Bukan ElectricCar.
Kalau kita memasukkannya ke Car:
abstract class Car {
void feature() {
print("Car feature");
}
void petrolEngine() {
print("Petrol engine");
}
void needsPetrol() {
print("Needs petrol");
}
}
Maka:
class ElectricCar extends Car {
}
juga mendapatkan:
electricCar.petrolEngine();
Padahal secara konsep salah.
Electric car tidak membutuhkan bensin.
14. Kenapa tidak membuat class PetrolVariant?
Misalnya:
class PetrolVariant {
void petrolEngine() {
print("Petrol engine");
}
void needsPetrol() {
print("Needs petrol");
}
}
Kemudian kita ingin:
class PetrolCar extends Car, PetrolVariant
Tidak bisa.
Dart tidak mendukung multiple superclass.
15. Bagaimana dengan implements?
Kita bisa membuat:
abstract class PetrolVariant {
void petrolEngine();
void needsPetrol();
}
Kemudian:
class PetrolCar extends Car implements PetrolVariant {
@override
void petrolEngine() {
print("Petrol engine");
}
@override
void needsPetrol() {
print("Needs petrol");
}
}
Masalahnya?
Kita harus menulis implementasi lagi.
Padahal kita ingin reuse code, bukan hanya contract.
Inilah tempat mixin sangat cocok.
16. Solusi dengan mixin
Kita buat:
mixin PetrolVariant {
void petrolEngine() {
print("Petrol engine");
}
void needsPetrol() {
print("Needs petrol");
}
}
Kemudian:
class PetrolCar extends Car with PetrolVariant {
}
Sekarang:
Car
↓
feature()
PetrolVariant
↓
petrolEngine()
needsPetrol()
↓
PetrolCar
PetrolCar mempunyai ketiga method tersebut.
17. ElectricVariant
Kita buat mixin lain:
mixin ElectricVariant {
void electricMotor() {
print("Electric motor");
}
void needsBattery() {
print("Needs battery");
}
}
Kemudian:
class ElectricCar extends Car with ElectricVariant {
}
Sekarang:
Car
↓
feature()
ElectricVariant
↓
electricMotor()
needsBattery()
↓
ElectricCar
18. HybridCar adalah contoh mixin yang sangat bagus
Hybrid membutuhkan dua kemampuan:
PetrolVariant
+
ElectricVariant
Maka:
class HybridCar extends Car
with PetrolVariant, ElectricVariant {
}
Sekarang HybridCar mendapatkan:
dari Car:
feature()
dari PetrolVariant:
petrolEngine()
needsPetrol()
dari ElectricVariant:
electricMotor()
needsBattery()
Ini jauh lebih bersih.
19. Bentuk keseluruhannya
Car
|
feature()
|
┌─────────┼─────────┐
│ │ │
↓ ↓ ↓
PetrolCar ElectricCar HybridCar
↑ ↑ ↑ ↑
│ │ │ │
PetrolVariant ElectricVariant │
│ │ │
└───────────┴─────────────┘
Lebih sederhananya:
PetrolCar
├── Car
│ └── feature()
│
└── PetrolVariant
├── petrolEngine()
└── needsPetrol()
ElectricCar
├── Car
│ └── feature()
│
└── ElectricVariant
├── electricMotor()
└── needsBattery()
HybridCar
├── Car
│ └── feature()
│
├── PetrolVariant
│ ├── petrolEngine()
│ └── needsPetrol()
│
└── ElectricVariant
├── electricMotor()
└── needsBattery()
Inilah inti alasan penggunaan mixin.
20. Mixin bukan inheritance
Ini penting.
Ketika:
class HybridCar extends Car with PetrolVariant, ElectricVariant {
}
Jangan membayangkan:
HybridCar
↑
PetrolVariant
↑
ElectricVariant
Bukan begitu.
Lebih baik bayangkan:
Car
↓
HybridCar
↙ ↘
PetrolVariant ElectricVariant
Car adalah superclass.
Sedangkan PetrolVariant dan ElectricVariant memberikan behavior melalui mixin.
21. Bagaimana kalau dua mixin memiliki method dengan nama sama?
Misalnya:
mixin A {
void hello() {
print("Hello from A");
}
}
mixin B {
void hello() {
print("Hello from B");
}
}
Kemudian:
class Test with A, B {
}
Kalau:
final test = Test();
test.hello();
Method mana yang digunakan?
Untuk mixin application, mixin yang lebih akhir biasanya memiliki precedence lebih tinggi.
Karena:
class Test with A, B
B diterapkan setelah A.
Maka:
Test
↑
B
↑
A
Sehingga hello() dari B akan menang.
Output:
Hello from B
Ini konsep penting ketika menggunakan banyak mixin.
22. Mixin dapat mempunyai abstract method
Mixin tidak harus berisi semua implementasi.
Misalnya:
mixin Logger {
void log(String message) {
print(message);
}
void saveLog();
}
Di sini:
log()
adalah concrete method.
Sedangkan:
saveLog()
adalah abstract method.
Class yang menggunakan mixin harus menyediakan implementasi saveLog() jika class tersebut concrete.
Contoh:
class App with Logger {
@override
void saveLog() {
print("Saving log...");
}
}
Sekarang:
final app = App();
app.log("Hello");
app.saveLog();
23. Mixin dapat memiliki this
Transcript juga membahas this.
Di dalam mixin, this mengacu kepada instance class yang menggunakan mixin tersebut.
Contoh:
mixin Greeter {
void greet() {
print("Hello");
print(this);
}
}
Kalau:
class Person with Greeter {
}
kemudian:
final person = Person();
person.greet();
this di dalam greet() mengacu pada object Person tersebut.
Jadi:
Person object
↑
this
↑
Greeter.greet()
24. Mixin tidak bisa memiliki constructor generative sendiri
Ini salah satu aturan penting.
Kita tidak bisa membuat:
mixin Test {
Test() {
print("Constructor");
}
}
❌ Tidak diperbolehkan.
Karena mixin tidak dibuat sebagai object secara langsung.
25. Mixin tidak bisa di-instansiasi
Ini masih berhubungan:
final test = Test();
❌ Tidak bisa jika Test adalah mixin.
Kita harus mempunyai class yang menggunakannya:
class Demo with Test {
}
kemudian:
final demo = Demo();
26. Mixin tidak menggunakan extends
Contoh:
mixin A extends B {
}
Pada bentuk mixin modern, mixin tidak bisa extends class seperti class biasa.
Kalau kita ingin membatasi bahwa mixin hanya boleh digunakan pada class tertentu, kita menggunakan keyword:
on
Nah, ini bagian terakhir transcript.
27. Apa fungsi keyword on?
on digunakan untuk membatasi siapa yang boleh menggunakan mixin.
Misalnya kita punya:
class Human {
void walk() {
print("Walking");
}
}
Kemudian:
mixin Speak on Human {
void speaking() {
print("Speaking");
}
}
Artinya:
Speakhanya boleh digunakan pada class yang merupakan subclass dariHuman.
28. Contoh yang diperbolehkan
class Student extends Human with Speak {
}
Ini boleh.
Karena:
Student
↓
Human
Student adalah subclass Human.
29. Contoh yang tidak diperbolehkan
Misalnya:
class Dog {
}
Kemudian:
class Dog with Speak {
}
❌ Tidak boleh.
Karena Dog bukan subclass Human.
30. Kenapa on berguna?
Sekarang bayangkan:
mixin Speak on Human {
void speaking() {
print(name);
}
}
Di dalam mixin kita mungkin ingin menggunakan property/method milik Human.
Misalnya:
class Human {
String name = "Unknown";
}
Kemudian:
mixin Speak on Human {
void speaking() {
print("$name is speaking");
}
}
Mengapa ini bisa?
Karena kita sudah memberitahu Dart:
on Human
Artinya mixin Speak hanya akan dipakai pada tipe yang memiliki Human sebagai superclass yang sesuai.
Jadi compiler tahu bahwa name tersedia.
31. Hal penting tentang on
Perhatikan:
mixin Speak on Human
Bukan berarti:
Speak mewarisi Human seperti
extends.
Lebih tepat:
Speak memiliki constraint bahwa dia hanya dapat diterapkan pada class yang merupakan subtype dari
Human.
Jadi on adalah constraint, bukan inheritance biasa.
32. Class yang disebut setelah on tidak boleh menggunakan mixin tersebut secara langsung
Ini bagian transcript yang sering membingungkan.
Misalnya:
mixin Speak on Human {
}
Apakah ini boleh?
class Human with Speak {
}
Dalam konsep penggunaan mixin dengan on, tidak boleh digunakan pada class yang menjadi constraint langsungnya.
Yang digunakan adalah subclass-nya.
Contoh:
class Human {
}
mixin Speak on Human {
}
class Student extends Human with Speak {
}
Ini adalah pola yang benar.
Jadi:
Human
↑
|
Student
↑
Speak boleh dipakai
33. on bisa menggunakan lebih dari satu constraint
Mixin juga bisa dibatasi pada beberapa superclass/interface constraint sesuai kemampuan Dart.
Contoh konsepnya:
mixin M on A, B {
}
Namun untuk pemula, yang paling penting pahami dulu pola sederhana:
mixin M on A
Artinya:
Mixin M hanya bisa diterapkan pada class yang kompatibel dengan A.
34. with vs implements pada mixin
Menariknya, mixin juga bisa digunakan sebagai interface.
Misalnya:
mixin Flyable {
void fly() {
print("Flying");
}
}
Dengan:
class Bird with Flyable {
}
Bird mendapatkan implementasi:
fly()
Tetapi:
class Bird implements Flyable {
}
berarti Bird memperlakukan Flyable sebagai interface contract.
Maka Bird harus menyediakan implementasi:
class Bird implements Flyable {
@override
void fly() {
print("Flying");
}
}
Jadi:
with
↓
ambil/reuse implementasi mixin
implements
↓
penuhi contract/interface
35. Mixin dan static member
Mixin juga bisa memiliki static member.
Contoh:
mixin Counter {
static int value = 0;
}
Static member diakses melalui nama declaration:
print(Counter.value);
Bukan melalui object:
final x = SomeClass();
x.value;
❌ Bukan seperti itu.
Hal ini sama dengan konsep static pada class yang sudah kita bahas sebelumnya.
36. Mixin dan super
Ini agak tricky.
Di dalam mixin kita bisa menggunakan super, tetapi maknanya bergantung pada bagaimana mixin tersebut diterapkan.
Contoh paling aman untuk pemahaman awal adalah:
mixin A {
void hello() {
print("Hello from A");
}
}
Kemudian:
class B {
void hello() {
print("Hello from B");
}
}
class C extends B with A {
}
Mixin dapat berinteraksi dengan superclass chain.
Ini adalah salah satu alasan kenapa konsep mixin sebenarnya lebih dalam daripada sekadar “copy-paste method”.
Mixin dapat dibuat untuk mengubah atau memperluas behavior superclass.
Namun untuk level pemula, cukup pegang:
superdalam mixin berkaitan dengan superclass/mixin application chain tempat mixin tersebut diterapkan, bukan berarti mixin memiliki superclass sendiri seperti class biasa.
37. Mixin vs class biasa
Mari kita bandingkan.
Class
class Animal {
void eat() {
print("Eating");
}
}
Bisa:
final animal = Animal();
Dan bisa:
class Cat extends Animal {
}
Mixin
mixin CanSwim {
void swim() {
print("Swimming");
}
}
Tidak bisa:
final x = CanSwim();
Tetapi:
class Duck with CanSwim {
}
38. Analogi kehidupan nyata
Bayangkan kamu sedang membuat karakter game.
Ada:
Character
Kemudian ada kemampuan:
CanFly
CanSwim
CanAttack
CanRun
Tidak masuk akal membuat:
CanFly
↓
Bird
sebagai inheritance utama jika CanFly hanya merupakan kemampuan.
Lebih masuk akal:
mixin CanFly {
void fly() {
print("Flying");
}
}
mixin CanSwim {
void swim() {
print("Swimming");
}
}
class Duck with CanFly, CanSwim {
}
Duck sekarang:
Duck
├── fly()
└── swim()
Sangat cocok dengan konsep mixin.
39. Contoh lain: Flutter
Mixin sangat relevan di Flutter.
Misalnya dalam Flutter kita sering melihat:
class MyPageState extends State<MyPage>
with TickerProviderStateMixin {
}
Di sini:
State<MyPage>
↑
extends
TickerProviderStateMixin
↑
with
Artinya:
State<MyPage>adalah superclass.TickerProviderStateMixinmemberikan behavior tambahan.- Kita tidak menjadikannya superclass dengan
extends.
Ini contoh nyata mengapa with penting untuk Flutter.
40. Kapan sebaiknya menggunakan mixin?
Gunakan mixin ketika:
1. Ada behavior yang bisa dipakai banyak class
Misalnya:
logging
validation
animation support
serialization helper
caching behavior
2. Behavior tersebut bukan hubungan IS-A
Misalnya:
Bird IS-A Animal
→ inheritance.
Tetapi:
Bird CAN-FLY
→ bisa menjadi mixin.
3. Beberapa class membutuhkan kemampuan yang sama
Misalnya:
PetrolCar → petrol behavior
HybridCar → petrol behavior
Maka:
mixin PetrolVariant {
}
41. Kapan jangan menggunakan mixin?
Jangan membuat mixin hanya karena:
“Saya ingin menghindari menulis beberapa baris kode.”
Pertimbangkan hubungan dan desainnya.
Kalau sebenarnya:
Cat IS-A Animal
maka:
class Cat extends Animal
lebih tepat.
Kalau:
Car HAS-A Engine
mungkin composition lebih tepat:
class Car {
final Engine engine;
Car(this.engine);
}
Sedangkan kalau:
Car CAN-DO-SOMETHING
dan behavior tersebut reusable, mixin mungkin cocok.
42. Perbandingan besar OOP yang perlu kamu kuasai
Sekarang kita gabungkan semua konsep yang sudah kita pelajari.
extends
class Cat extends Animal
Maknanya:
Cat adalah Animal.
Mendapatkan inheritance dan implementation dari superclass.
Hanya satu superclass langsung.
implements
class Cat implements Animal
Maknanya:
Cat berjanji memenuhi contract Animal.
Tidak mendapatkan implementasi instance dari Animal.
Bisa multiple:
class Cat implements Animal, Pet
with
class Cat with CanClimb
Maknanya:
Cat menggunakan behavior dari mixin
CanClimb.
Bisa banyak:
class Cat with CanClimb, CanRun, CanJump
on
mixin CanSpeak on Human
Maknanya:
Mixin
CanSpeakhanya boleh diterapkan pada class yang kompatibel denganHuman.
43. Cheat sheet
| Keyword | Pertanyaan yang dijawab |
|---|---|
extends | “Class ini adalah turunan dari siapa?” |
implements | “Class ini memenuhi contract siapa?” |
with | “Class ini mengambil behavior tambahan dari siapa?” |
on | “Mixin ini boleh digunakan pada class apa?” |
super | “Bagaimana mengakses superclass?” |
this | “Bagaimana mengakses object saat ini?” |
44. Contoh lengkap
Kalau kita gabungkan semuanya:
abstract class Car {
void feature() {
print("General car feature");
}
}
mixin PetrolVariant {
void petrolEngine() {
print("Petrol engine");
}
void needsPetrol() {
print("Needs petrol");
}
}
mixin ElectricVariant {
void electricMotor() {
print("Electric motor");
}
void needsBattery() {
print("Needs battery");
}
}
class PetrolCar extends Car with PetrolVariant {
}
class ElectricCar extends Car with ElectricVariant {
}
class HybridCar extends Car
with PetrolVariant, ElectricVariant {
}
Kemudian:
void main() {
final petrol = PetrolCar();
petrol.feature();
petrol.petrolEngine();
petrol.needsPetrol();
final electric = ElectricCar();
electric.feature();
electric.electricMotor();
electric.needsBattery();
final hybrid = HybridCar();
hybrid.feature();
hybrid.petrolEngine();
hybrid.needsPetrol();
hybrid.electricMotor();
hybrid.needsBattery();
}
Secara konsep hasilnya:
PetrolCar
├── feature()
├── petrolEngine()
└── needsPetrol()
ElectricCar
├── feature()
├── electricMotor()
└── needsBattery()
HybridCar
├── feature()
├── petrolEngine()
├── needsPetrol()
├── electricMotor()
└── needsBattery()
Ini jauh lebih baik daripada memasukkan semua method ke Car.
45. Koreksi beberapa bagian transcript
Ada beberapa bagian transcript yang sebaiknya kamu catat supaya tidak membawa pemahaman yang kurang tepat.
❌ “Mixin adalah class”
Lebih tepat:
Mixin adalah mekanisme/type declaration untuk menyediakan behavior yang dapat diterapkan ke class lain.
Memang bentuknya mirip class dan memiliki banyak fitur seperti class, tetapi mixin bukan class biasa yang dapat di-instansiasi.
❌ “Regular class bisa menjadi mixin”
Transcript menyebut class biasa tanpa constructor dan tidak extends class lain dapat digunakan sebagai mixin.
Ini berkaitan dengan legacy/older Dart syntax.
Untuk Dart modern, sebaiknya kamu fokus pada:
mixin MyMixin {
}
Jangan membangun pemahaman baru berdasarkan pola legacy tersebut.
❌ “Mixin tidak boleh extend class”
Untuk declaration:
mixin MyMixin
memang bukan class yang bisa menggunakan extends seperti class biasa.
Kalau perlu constraint, gunakan:
mixin MyMixin on SomeClass {
}
❌ “Mixin seperti interface”
Tidak persis.
Perbedaannya:
implements
→ contract.
Sedangkan:
with
→ reuse behavior/implementation.
❌ “Mixin seperti multiple inheritance”
Jangan menyebutnya multiple inheritance secara literal.
Lebih aman:
Dart menggunakan mixin untuk memungkinkan sebuah class memperoleh behavior dari beberapa sumber tanpa multiple superclass inheritance.
46. Cara paling mudah mengingat Mixin
Kalau kamu lupa semuanya, ingat kalimat ini:
extends= mewarisi identitas,implements= memenuhi contract,with= menambahkan kemampuan.
Contoh:
class Cat extends Animal
Cat adalah Animal.
class Cat implements Pet
Cat memenuhi contract Pet.
class Cat with CanClimb
Cat memiliki kemampuan untuk climbing.
Dan:
mixin CanClimb on Animal
berarti:
Kemampuan
CanClimbhanya boleh ditempelkan pada class yang sesuai dengan constraintAnimal.
47. Gambaran besar
Setelah mempelajari inheritance, interface, overriding, super, dan sekarang mixin, kamu bisa melihat OOP Dart seperti ini:
OOP Dart
│
┌────────────────┼─────────────────┐
↓ ↓ ↓
extends implements with
│ │ │
IS-A CONTRACT BEHAVIOR
│ │ │
↓ ↓ ↓
inheritance interface mixin
Dan on:
mixin X on A
│
↓
"X hanya boleh digunakan pada
class yang kompatibel dengan A"
Kalau dikaitkan dengan contoh mobil:
Car
│
extends
│
┌─────────────┼─────────────┐
↓ ↓ ↓
PetrolCar ElectricCar HybridCar
│ │ │
with with with
│ │ ┌──┴──┐
↓ ↓ ↓ ↓
PetrolVariant ElectricVariant Petrol Electric
Jadi inti video ini bukan sekadar “cara memakai with”. Intinya adalah memahami bahwa inheritance tidak selalu menjadi solusi untuk reuse behavior. Ketika beberapa class membutuhkan kemampuan yang sama tetapi kemampuan tersebut bukan hubungan IS-A, mixin sering menjadi solusi yang lebih tepat.