Masukkan Password
58 Solving all doubts for Mixins in Dart | Dart mixin questions and answers
Video ini adalah lanjutan dari pembahasan Mixin di Dart, dan fokusnya sangat bagus karena membahas 20 pertanyaan yang sering membuat pemula bingung.
Saya akan menjelaskannya satu per satu dengan bahasa sederhana. Saya juga akan mengoreksi beberapa bagian transcript yang kurang tepat, terutama tentang hubungan mixin, implements, super, dan inheritance.
Gambaran besar dulu
Sebelum masuk 20 pertanyaan, pegang dulu empat keyword ini:
extends
with
implements
on
Secara sederhana:
| Keyword | Makna |
|---|---|
extends | mewarisi dari superclass |
with | menggunakan mixin |
implements | memenuhi contract/interface |
on | membatasi mixin agar hanya bisa dipakai pada tipe tertentu |
Contoh:
class Dog extends Animal with CanRun implements Pet {
}
Artinya:
Dog
│
├── extends Animal
│ → inheritance
│
├── with CanRun
│ → menggunakan behavior dari mixin
│
└── implements Pet
→ memenuhi contract Pet
Dan urutan syntax-nya memang:
extends → with → implements
1. Bagaimana satu class bisa menggunakan banyak mixin?
Ini pertanyaan pertama dan sangat penting.
Kita tahu Dart tidak mengizinkan:
class Zoo extends Fish, Dog {
}
❌ Tidak boleh.
Kenapa?
Misalnya:
class Fish {
void eat() {
print("Fish is eating");
}
}
class Dog {
void eat() {
print("Dog is eating");
}
}
Bayangkan kalau Dart memperbolehkan:
class Zoo extends Fish, Dog {
}
Maka Zoo akan memiliki dua eat():
Fish.eat()
Dog.eat()
Kemudian:
final zoo = Zoo();
zoo.eat();
Pertanyaannya:
Harus menjalankan
Fish.eat()atauDog.eat()?
Ini bisa menimbulkan konflik/ambiguity.
Karena itu Dart hanya mempunyai satu superclass langsung melalui extends.
2. Lalu kenapa mixin boleh banyak?
Karena mixin menggunakan mekanisme yang berbeda.
mixin Fish {
void eat() {
print("Fish is eating");
}
}
mixin Dog {
void eat() {
print("Dog is eating");
}
}
Kita bisa:
class Zoo with Fish, Dog {
}
Ini diperbolehkan.
Kalau keduanya punya method yang sama:
zoo.eat();
mixin yang diterapkan paling akhir mempunyai precedence lebih tinggi.
Jadi:
class Zoo with Fish, Dog
akan menggunakan Dog.eat().
Output:
Dog is eating
Kalau dibalik:
class Zoo with Dog, Fish
maka:
Fish is eating
3. Bayangkan mixin seperti tumpukan
Cara mudah memahaminya adalah menggunakan analogi stack.
Misalnya:
class Zoo with Fish, Dog
Bayangkan:
Zoo
↑
Dog ← paling atas
↑
Fish
↑
superclass
Kalau Fish dan Dog sama-sama punya:
eat()
maka Dog.eat() yang lebih dekat dengan Zoo akan digunakan.
Jadi urutan mixin penting.
4. Kalau method mixin berbeda namanya?
Tidak ada masalah.
mixin Fish {
void swim() {
print("Swimming");
}
}
mixin Dog {
void bark() {
print("Barking");
}
}
class Zoo with Fish, Dog {
}
Sekarang:
final zoo = Zoo();
zoo.swim();
zoo.bark();
Output:
Swimming
Barking
Tidak ada konflik karena nama method berbeda.
5. Apakah mixin boleh mempunyai constructor?
Jawabannya:
❌ Mixin tidak boleh memiliki generative constructor sendiri.
Misalnya:
mixin Person {
Person() {
print("Constructor");
}
}
Tidak diperbolehkan.
Kenapa?
Karena mixin bukan object yang kita instantiate secara langsung.
Kita tidak melakukan:
final p = Person();
Mixin digunakan sebagai behavior:
class Student with Person {
}
6. Bagaimana dengan class yang digunakan sebagai mixin?
Transcript membahas bahwa versi tertentu Dart memungkinkan class tertentu digunakan sebagai mixin.
Secara historis ada aturan seperti:
class Helper {
void hello() {
print("Hello");
}
}
kemudian class tersebut bisa digunakan dalam posisi mixin jika memenuhi aturan tertentu.
Tetapi untuk Dart modern, sebaiknya jangan menjadikan pola legacy tersebut sebagai fokus utama.
Gunakan deklarasi yang memang dibuat untuk mixin:
mixin Helper {
void hello() {
print("Hello");
}
}
Ini jauh lebih jelas.
7. Apakah mixin boleh extends class?
Secara deklarasi mixin:
mixin A extends B {
}
❌ Tidak seperti inheritance class biasa.
Mixin bukan subclass biasa.
Kalau ingin membatasi mixin agar hanya dapat digunakan pada class tertentu, gunakan:
mixin A on B {
}
Ini berbeda.
extends
↓
inheritance
on
↓
constraint/batas penggunaan mixin
8. Apakah mixin boleh implements interface?
Ya.
Contoh:
abstract class Animal {
void eat();
}
mixin DogBehavior implements Animal {
@override
void eat() {
print("Dog eating");
}
void bark() {
print("Barking");
}
}
Mixin DogBehavior memenuhi contract Animal.
Namun hati-hati:
implements
tidak berarti:
“Saya mendapatkan implementation dari Animal.”
Justru:
“Saya berjanji memenuhi contract Animal.”
9. Mixin bisa mempunyai abstract method
Misalnya:
mixin HumanBehavior {
void think() {
print("Thinking");
}
void speak();
}
Ada dua method:
think()
→ concrete
speak()
→ abstract
Kemudian:
class Man with HumanBehavior {
}
Ini akan bermasalah karena Man belum menyediakan speak().
Harus:
class Man with HumanBehavior {
@override
void speak() {
print("Speaking");
}
}
Sekarang lengkap.
10. Apakah mixin bisa implements mixin lain?
Bisa diperlakukan sebagai interface.
Misalnya:
mixin Employee {
void work() {
print("Working");
}
}
mixin Manager implements Employee {
}
Namun Manager tidak mendapatkan implementation work() dari Employee hanya karena menggunakan implements.
Karena:
implements Employee
berarti:
Manager harus memenuhi contract Employee.
Jika work() tidak diimplementasikan oleh Manager, maka class yang nantinya menggunakan Manager harus memenuhi method tersebut.
Ini sama seperti konsep interface yang kita pelajari sebelumnya.
11. Apakah object mixin bisa dibuat?
Tidak.
mixin CanSwim {
void swim() {
print("Swimming");
}
}
Tidak bisa:
final x = CanSwim();
❌
Tetapi:
class Duck with CanSwim {
}
lalu:
final duck = Duck();
✅
Dan:
duck.swim();
12. Apakah super bisa digunakan untuk mengakses method dari mixin?
Ini bagian transcript yang perlu dipahami dengan hati-hati.
Misalnya:
mixin AnimalBehavior {
int numberOfLegs = 4;
void eat() {
print("Animal is eating");
}
}
class Dog with AnimalBehavior {
void showData() {
print(super.numberOfLegs);
super.eat();
}
}
Dalam konteks mixin application seperti ini, super dapat digunakan untuk mengakses member dari bagian superclass/mixin chain yang relevan.
Tetapi jangan membuat mental model:
“Mixin adalah superclass dari Dog.”
Bukan begitu.
Lebih aman membayangkan bahwa Dart membangun class hierarchy/mixin application chain, dan super mengacu ke implementation/member yang berada pada level superclass/mixin sebelumnya dalam chain.
13. super bukan berarti “object parent”
Ini penting karena sebelumnya kita sudah membahas super.
Jangan bayangkan:
super → object parent
sebagai object terpisah.
Lebih tepat:
superadalah keyword untuk mengakses member atau constructor dari superclass/mixin application chain pada posisi tersebut.
14. Apakah method mixin bisa di-override?
Ya.
Misalnya:
mixin AnimalBehavior {
void sound() {
print("Animal sound");
}
}
Kemudian:
class Cat with AnimalBehavior {
@override
void sound() {
print("Meow");
}
}
Sekarang:
final cat = Cat();
cat.sound();
Output:
Meow
Method dari mixin bisa diganti oleh class yang menggunakan mixin.
15. Concrete method vs abstract method
Ini harus benar-benar dibedakan.
Concrete
mixin Animal {
void eat() {
print("Eating");
}
}
Class boleh override:
class Cat with Animal {
@override
void eat() {
print("Cat eating");
}
}
Tetapi tidak wajib.
Abstract
mixin Animal {
void eat();
}
Maka class concrete yang menggunakan mixin harus menyediakan:
class Cat with Animal {
@override
void eat() {
print("Cat eating");
}
}
16. Apakah mixin bisa menjadi parameter function?
Ini menarik.
Transcript mengatakan:
Tidak bisa membuat object mixin, tetapi tipe mixin dapat digunakan sebagai parameter.
Contoh:
mixin Person {
void sayHello() {
print("Hello");
}
}
Kemudian:
class Employee with Person {
}
Kita bisa memiliki function yang menerima tipe tersebut:
void test(Person person) {
person.sayHello();
}
Lalu:
final employee = Employee();
test(employee);
Kenapa bisa?
Karena Employee adalah class yang telah mengadopsi mixin Person.
Jadi object yang dikirim adalah:
Employee object
bukan object:
Person mixin
17. Analogi superclass reference
Secara mental kamu bisa membayangkannya seperti:
Person
↑
Employee
Kemudian:
Person person = employee;
Konsepnya adalah object employee memenuhi tipe yang diperlukan.
Yang penting:
Kita tidak membuat
Person()kalauPersonadalah mixin.
Kita membuat Employee().
18. on untuk membatasi mixin
Sekarang kita masuk ke salah satu fitur terpenting.
Misalnya:
class Human {
}
Kemudian:
mixin Speak on Human {
void speaking() {
print("Speaking");
}
}
Artinya:
Speakhanya boleh digunakan pada class yang kompatibel denganHuman.
19. Contoh yang boleh
class Man extends Human with Speak {
}
Boleh karena:
Man
↓
Human
Man adalah subclass Human.
20. Contoh yang tidak boleh
class Dog {
}
class Dog with Speak {
}
Tidak boleh.
Karena:
Dog
tidak memiliki hubungan yang diperlukan dengan:
Human
21. Direct subclass maupun indirect subclass
Misalnya:
class Human {
}
mixin Speak on Human {
void speak() {
print("Speaking");
}
}
class Man extends Human with Speak {
}
Boleh.
Sekarang:
class SuperMan extends Man with Speak {
}
Secara konsep constraint Human juga terpenuhi melalui rantai:
SuperMan
↓
Man
↓
Human
Jadi constraint dapat terpenuhi secara tidak langsung.
Namun perlu hati-hati: kita tidak perlu terus menempelkan Speak pada subclass yang sudah mewarisi behavior tersebut. Misalnya jika Man sudah with Speak, SuperMan extends Man sudah mewarisi behavior itu.
22. Kenapa on berguna?
Misalnya:
class Human {
String name = "Unknown";
}
mixin Speak on Human {
void speaking() {
print("$name is speaking");
}
}
Mixin Speak menggunakan:
name
yang berasal dari Human.
Dengan:
on Human
kita memberi tahu Dart:
Mixin ini hanya boleh dipakai pada class yang memiliki hubungan yang sesuai dengan
Human.
Jadi Speak bisa bergantung pada kemampuan/member dari Human.
23. Apakah class Human sendiri boleh langsung menggunakan Speak?
Untuk pola constraint ini, jangan menganggap:
class Human with Speak
sebagai penggunaan yang valid dari constraint on Human.
Pola yang dimaksud adalah mixin tersebut digunakan oleh subclass/tipe yang memenuhi constraint.
Contoh yang jelas:
class Human {
}
mixin Speak on Human {
}
class Man extends Human with Speak {
}
24. Apakah class biasa bisa digunakan sebagai mixin?
Ini adalah bagian transcript yang berasal dari aturan Dart yang lebih lama.
Untuk Dart modern, gunakan:
mixin MyMixin {
}
daripada mengandalkan class sebagai mixin.
Kalau kamu sedang belajar Dart sekarang, pola utama yang harus kamu hafal adalah:
mixin MyMixin {
}
25. Apakah mixin boleh mempunyai static member?
Ya.
Contoh:
mixin MyMath {
static const pi = 3.14159;
static int cube(int n) {
return n * n * n;
}
}
Gunakan:
print(MyMath.pi);
print(MyMath.cube(2));
Output:
3.14159
8
Bukan:
final x = SomeClass();
x.pi;
Static member diakses melalui declaration name:
MyMath.pi
26. Instance member vs static member pada mixin
Misalnya:
mixin Test {
int x = 10;
static int y = 20;
}
x adalah instance member.
Untuk menggunakan x, kita membutuhkan object dari class yang memakai mixin:
class Demo with Test {
}
final demo = Demo();
print(demo.x);
Sedangkan y adalah static:
print(Test.y);
Jadi:
instance member
→ object class pengguna mixin
static member
→ nama mixin
27. Kalau mixin punya abstract method, siapa yang harus mengimplementasikan?
Class yang menggunakan mixin.
Misalnya:
mixin Worker {
void work();
}
Kemudian:
class Employee with Worker {
@override
void work() {
print("Employee working");
}
}
Employee harus memenuhi abstract method tersebut.
Kalau tidak:
class Employee with Worker {
}
akan bermasalah jika Employee adalah concrete class.
Alternatifnya, Employee bisa dibuat abstract dan menyerahkan implementasi kepada subclass.
28. Mana yang lebih bagus: class, interface, atau mixin?
Tidak ada yang “paling bagus” secara universal.
Masing-masing mempunyai tujuan.
Gunakan class ketika…
Kamu membutuhkan object.
class Car {
}
Kemudian:
final car = Car();
Gunakan interface ketika…
Kamu ingin menentukan contract.
Misalnya:
abstract class Payment {
void pay(double amount);
}
Kemudian:
class CreditCard implements Payment {
@override
void pay(double amount) {
print("Pay with credit card");
}
}
Gunakan mixin ketika…
Kamu ingin reuse behavior/implementation pada beberapa class.
mixin Logger {
void log(String message) {
print(message);
}
}
Kemudian:
class UserService with Logger {
}
class PaymentService with Logger {
}
Keduanya mendapatkan:
log()
tanpa perlu membuat inheritance yang tidak tepat.
29. Class vs Interface vs Mixin
Cara paling gampang:
CLASS
↓
"buat object"
INTERFACE
↓
"ikuti contract saya"
MIXIN
↓
"ambil kemampuan/behavior saya"
30. Bagaimana kalau dua mixin memiliki method yang sama tetapi signature berbeda?
Misalnya:
mixin Paper {
void paint() {
print("Paper");
}
}
mixin Canvas {
void paint(int width, int height) {
print("Canvas");
}
}
Kemudian:
class Painter with Paper, Canvas {
}
Ini bermasalah.
Kenapa?
Karena ada dua member bernama:
paint()
paint(int, int)
Dart tidak memiliki traditional method overloading seperti Java/C++.
Jadi jangan membayangkan Dart akan memilih berdasarkan jumlah parameter seperti:
paint() → Paper
paint(100, 200) → Canvas
Tidak seperti itu.
Ini bisa menghasilkan konflik pada mixin application.
31. Dart tidak mempunyai traditional method overloading
Ini sangat penting.
Di Java misalnya:
void paint() {}
void paint(int width, int height) {}
bisa menjadi overload.
Di Dart, kita tidak menggunakan mekanisme tersebut sebagai traditional method overloading.
Sebagai gantinya biasanya digunakan:
- optional positional parameter
- named parameter
- optional named parameter
Misalnya:
void paint([int? width, int? height]) {
}
atau:
void paint({int? width, int? height}) {
}
32. Bagaimana jika superclass dan mixin mempunyai method yang sama?
Ini pertanyaan nomor 16.
Misalnya:
class Father {
void giveToSon() {
print("Father gives to son");
}
}
Kemudian:
mixin Mother {
void giveToSon() {
print("Mother gives to son");
}
}
Lalu:
class Son extends Father with Mother {
}
Ketika:
final son = Son();
son.giveToSon();
yang dipilih adalah implementasi dari mixin yang diterapkan tersebut.
Output:
Mother gives to son
Mengapa?
Karena mixin application berada lebih dekat dengan Son dibanding implementation superclass Father.
Secara mental:
Son
↑
Mother mixin
↑
Father
Method dari Mother menutupi/replaces method dengan nama yang sama dari Father dalam resulting class behavior.
33. Bagaimana kalau mixin ingin memanggil implementation superclass?
Di sinilah super menjadi menarik.
Misalnya:
class Father {
void giveToSon() {
print("Father gives to son");
}
}
mixin Mother {
void giveToSon() {
super.giveToSon();
print("Mother gives to son");
}
}
Dengan penerapan yang sesuai, super dapat digunakan untuk meneruskan ke implementation sebelumnya dalam chain.
Konsepnya mirip:
Mother.giveToSon()
↓
super.giveToSon()
↓
Father.giveToSon()
Namun ini bergantung pada constraint dan bentuk mixin application. Jangan menganggap super dalam mixin berarti “panggil superclass milik mixin”, karena mixin sendiri bukan subclass biasa.
34. Apakah mixin dibuat untuk multiple inheritance?
Jawaban yang lebih tepat:
Tidak tepat mengatakan mixin adalah multiple inheritance.
Mixin memang memungkinkan sebuah class memperoleh behavior dari beberapa mixin:
class HybridCar extends Car
with PetrolVariant, ElectricVariant {
}
Tetapi tujuan utamanya adalah behavior reuse/composition melalui mixin, bukan membuat multiple superclass inheritance.
Mental model yang lebih baik:
extends
→ satu superclass
with
→ banyak behavior
35. Kenapa contoh mobil tadi cocok sekali untuk mixin?
Karena:
PetrolCar
HybridCar
sama-sama membutuhkan:
PetrolVariant
Sedangkan:
ElectricCar
HybridCar
sama-sama membutuhkan:
ElectricVariant
Sehingga:
Car
│
┌──────┼──────┐
↓ ↓ ↓
Petrol Electric Hybrid
│ │ │
↓ ↓ ↓
Petrol Electric Petrol + Electric
mixin mixin mixin
Ini reuse behavior yang sangat natural.
36. Apakah class bisa extends mixin?
Tidak.
Misalnya:
mixin Work {
void work() {
print("Working");
}
}
Tidak:
class Man extends Work {
}
❌
Tetapi:
class Man with Work {
}
✅
Atau:
class Man implements Work {
@override
void work() {
print("Working");
}
}
✅
Tapi implements hanya mengambil contract/interface, bukan implementation work().
37. Inilah perbedaan with dan implements pada mixin
Misalnya:
mixin Work {
void work() {
print("Working");
}
}
with
class Man with Work {
}
Man mendapatkan implementation:
work()
implements
class Man implements Work {
}
Man tidak otomatis mendapatkan body work().
Harus:
class Man implements Work {
@override
void work() {
print("Working");
}
}
Jadi:
with
→ reuse implementation
implements
→ fulfill contract
38. Apakah method dari mixin diwariskan ke subclass?
Ya.
Misalnya:
mixin Fly {
void flying() {
print("Flying");
}
}
class Bird with Fly {
}
class Parrot extends Bird {
}
Sekarang:
final parrot = Parrot();
parrot.flying();
Output:
Flying
Kenapa?
Karena Bird mendapatkan flying() dari mixin Fly.
Kemudian Parrot merupakan subclass dari Bird, sehingga Parrot juga dapat mengakses member yang diwarisi Bird.
Jadi:
Fly
↓ with
Bird
↓ extends
Parrot
Behavior dari mixin dapat tersedia pada level inheritance berikutnya.
39. Ini berbeda dengan “mixin ditempel ulang”
Perhatikan:
class Bird with Fly {
}
class Parrot extends Bird {
}
Kita tidak perlu:
class Parrot extends Bird with Fly {
}
karena Parrot sudah mewarisi Bird, dan Bird sudah mempunyai behavior dari Fly.
40. Urutan extends, with, implements
Ini pertanyaan terakhir.
Misalnya kita punya:
class Animal {
}
mixin CanRun {
void run() {
print("Running");
}
}
abstract class Pet {
void play();
}
Kita ingin menggunakan ketiganya.
Urutannya:
class Dog extends Animal with CanRun implements Pet {
@override
void play() {
print("Playing");
}
}
Urutannya:
extends
↓
with
↓
implements
Tidak boleh dibolak-balik sembarangan.
41. Bisa menggunakan banyak interface
Ya.
class Dog
extends Animal
with CanRun, CanSwim
implements Pet, DomesticAnimal {
}
Strukturnya:
extends
↓
Animal
with
↓
CanRun
CanSwim
implements
↓
Pet
DomesticAnimal
Dan ini sangat umum dalam Dart/Flutter.
42. Ringkasan 20 pertanyaan
Sekarang kita buat cheat sheet.
| No | Pertanyaan | Jawaban |
|---|---|---|
| 1 | Banyak mixin dalam satu class? | ✅ Bisa |
| 2 | Constructor dalam mixin? | ❌ Tidak |
| 3 | Mixin extends class? | ❌ Bukan seperti class biasa |
| 4 | Mixin implements interface? | ✅ Bisa |
| 5 | Mixin implements mixin? | ✅ Bisa sebagai contract |
| 6 | Object mixin? | ❌ Tidak |
| 7 | super pada mixin/class yang memakai mixin? | ✅ Bisa sesuai member chain |
| 8 | Abstract method dalam mixin? | ✅ Bisa |
| 9 | Override method mixin? | ✅ Bisa |
| 10 | Batasi mixin? | ✅ on |
| 11 | Class sebagai mixin? | Ada aturan legacy; untuk Dart modern gunakan mixin |
| 12 | Static member? | ✅ Bisa |
| 13 | Abstract method harus diimplementasi? | ✅ Oleh concrete class pengguna |
| 14 | Class/interface/mixin mana terbaik? | Tergantung kebutuhan |
| 15 | Dua method sama tapi signature berbeda? | Bisa konflik; Dart tidak punya traditional overloading |
| 16 | Superclass dan mixin method sama? | Mixin application lebih dekat → biasanya mixin yang menang |
| 17 | Mixin = multiple inheritance? | ❌ Jangan dipahami begitu |
| 18 | Class extends mixin? | ❌ |
| 19 | Mixin behavior tersedia di subclass? | ✅ Melalui inheritance |
| 20 | Urutan extends, with, implements? | extends → with → implements |
43. Cheat sheet paling penting
Kalau kamu ingin menghafal materi video ini tanpa menghafal 20 jawaban, cukup pahami struktur ini:
CLASS
│
┌──────────┼───────────┐
│ │ │
extends implements with
│ │ │
↓ ↓ ↓
inheritance contract behavior
│ │ │
IS-A HARUS IKUT PAKAI
ATURAN
Kemudian:
mixin X on A
berarti:
X hanya boleh digunakan
pada class yang memenuhi
constraint A
44. Hubungkan dengan materi sebelumnya
Kalau semua materi OOP yang sudah kamu pelajari digabung, gambar besarnya menjadi:
OOP DART
│
┌───────────┼────────────┐
↓ ↓ ↓
Inheritance Interface Mixin
│ │ │
extends implements with
│ │ │
IS-A CONTRACT BEHAVIOR
│ │ │
↓ ↓ ↓
superclass wajib punya reuse code
Kemudian:
@override
digunakan ketika kita memberikan implementasi baru.
super
digunakan untuk mengakses implementation/member dari level superclass/mixin chain sebelumnya.
Dan:
on
digunakan untuk membatasi tempat mixin boleh diterapkan.
45. Satu contoh final yang menggabungkan semuanya
abstract class Animal {
void eat() {
print("Animal eating");
}
}
mixin CanRun {
void run() {
print("Running");
}
}
mixin CanSwim {
void swim() {
print("Swimming");
}
}
abstract class Pet {
void play();
}
class Dog extends Animal
with CanRun, CanSwim
implements Pet {
@override
void play() {
print("Dog playing");
}
@override
void eat() {
super.eat();
print("Dog eating");
}
}
Sekarang:
void main() {
final dog = Dog();
dog.eat();
dog.run();
dog.swim();
dog.play();
}
Kita bisa membaca class tersebut seperti ini:
Dog
│
├── extends Animal
│ └── mendapatkan inheritance
│
├── with CanRun
│ └── mendapatkan run()
│
├── with CanSwim
│ └── mendapatkan swim()
│
└── implements Pet
└── wajib menyediakan play()
Dan:
super.eat();
berarti:
“Jalankan implementation
eat()dari level superclassAnimal.”
Inti yang harus benar-benar kamu kuasai
Kalau setelah menonton video ini kamu hanya mengingat 5 hal, ingat ini:
1. extends hanya punya satu superclass langsung.
class Dog extends Animal
2. with digunakan untuk mixin dan bisa banyak.
class Dog with CanRun, CanSwim
3. Mixin digunakan terutama untuk reuse behavior/code, bukan sebagai object.
mixin CanRun {
void run() {}
}
4. implements berbeda dengan with.
with
→ mendapatkan/reuse implementation
implements
→ hanya memenuhi contract
5. on membatasi mixin.
mixin CanSpeak on Human
Artinya CanSpeak hanya bisa diterapkan pada class yang memenuhi constraint Human.
Dan satu kalimat yang menurut saya paling bagus untuk kamu pegang:
extends= “saya adalah turunan dari X”,implements= “saya memenuhi contract X”,with= “saya mengambil kemampuan X”, danon= “kemampuan ini hanya boleh dipakai oleh tipe tertentu.”