Mixins vs Pewarisan
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan Lua di Coddy. Pelajaran 53 dari 70.
Kamu sudah mempelajari dua cara untuk berbagi perilaku: inheritance menciptakan hubungan "is-a" melalui rantai prototype, sedangkan mixins menyalin fungsi langsung ke dalam class. Namun, kapan kamu sebaiknya menggunakan masing-masing pendekatan?
Gunakan pewarisan saat object memiliki identitas mendasar yang sama. Bird adalah Animal. Masuk akal jika Bird mewarisi perilaku dasar hewan seperti :eat() atau :sleep(). Hubungan ini bersifat permanen dan menentukan hakikat object tersebut.
Gunakan mixins saat kamu ingin menambahkan kemampuan yang tidak menentukan identitas inti object.
Tidak semua burung bisa terbang: penguin dan burung unta adalah burung, tetapi mereka tidak terbang. Terbang adalah kemampuan, bukan sifat yang menentukan apakah sesuatu adalah burung. Mixin Flyable memungkinkan kamu menambahkan kemampuan terbang pada burung yang membutuhkannya, tanpa memaksakannya pada semua burung.
Kedua pendekatan ini bekerja dengan sangat baik bersama-sama:
-- Bird mewarisi Animal (hubungan is-a)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})
-- Flyable adalah kemampuan (mixin)
local Flyable = {}
function Flyable:fly()
print(self.name .. " soars through the sky!")
end
-- Terapkan mixin hanya pada burung yang bisa terbang
applyMixin(Bird, Flyable)Pola ini memberimu keunggulan dari kedua sisi: hierarki class yang jelas untuk identitas bersama, ditambah kemampuan fleksibel yang dapat dicampurkan sesuai kebutuhan.
Tantangan
MudahMari buat ekosistem kecil berisi makhluk yang menunjukkan kapan sebaiknya menggunakan pewarisan dibandingkan mixin! Kamu akan membuat class dasar Animal, Bird yang mewarisinya, dan mixin Swimmable, karena meskipun semua burung adalah hewan, tidak semua burung bisa berenang.
Kamu akan mengatur kodemu dalam empat file:
Animal.lua: Buat class dasar Animal dengan konstruktor:new(name)yang menyimpan nama. Sertakan method:eat()yang mencetak{name} is eating. Ini mewakili identitas inti yang dimiliki semua hewan.Swimmable.lua: Buat mixin dengan method:swim()yang mencetak{self.name} is swimming. Ini adalah kemampuan, tidak semua makhluk bisa berenang, jadi kemampuan ini sebaiknya tidak menjadi bagian dari rantai pewarisan.Bird.lua: Buat class Bird yang mewarisi Animal. Konstruktor:new(name, canSwim)harus memanggil konstruktor induk dan menyimpan apakah burung ini bisa berenang. Terapkan mixin Swimmable ke class Bird. Sertakan method:chirp()yang mencetak{name} chirps!. Ini adalah perilaku khusus burung.main.lua: Tulis fungsi helperapplyMixindi sini. Baca input untuk nama burung dan apakah burung itu bisa berenang (yesatauno). Buat instance Bird, lalu tunjukkan kemampuannya: panggil:eat()(diwarisi dari Animal), panggil:chirp()(method milik Bird), dan panggil:swim()hanya jika burung itu bisa berenang.
Kamu akan menerima dua input:
- Nama burung (sebuah string)
- Apakah burung itu bisa berenang:
yesatauno
Jika burung itu bisa berenang, output-mu harus seperti ini:
{name} is eating
{name} chirps!
{name} is swimmingJika burung itu tidak bisa berenang, output-mu harus seperti ini:
{name} is eating
{name} chirps!Misalnya, jika inputnya adalah Duck dan yes, output-nya harus seperti ini:
Duck is eating
Duck chirps!
Duck is swimmingJika inputnya adalah Sparrow dan no, output-nya harus seperti ini:
Sparrow is eating
Sparrow chirps!Tantangan ini menunjukkan perbedaan utamanya: Bird adalah seekor Animal (pewarisan), tetapi berenang adalah kemampuan opsional (mixin). Mixin diterapkan ke class, tetapi logika utama programmu menentukan apakah kemampuan itu digunakan berdasarkan kemampuan tiap burung!
Coba sendiri
-- main.lua: Titik awal, buat burung dan tunjukkan kemampuannya
-- Fungsi pembantu untuk menerapkan mixin ke class
local function applyMixin(class, mixin)
-- TODO: Salin semua method dari mixin ke class
end
-- Terapkan mixin Swimmable ke Bird sebelum memuat Bird dengan require
-- Note: Kamu mungkin perlu menangani ini di Bird.lua atau di sini
local Bird = require('Bird')
local Swimmable = require('Swimmable')
-- Terapkan mixin ke class Bird
applyMixin(Bird, Swimmable)
-- Baca input
local name = io.read()
local canSwimInput = io.read()
-- TODO: Tentukan apakah burung dapat berenang berdasarkan input ("yes" atau "no")
-- TODO: Buat instance Bird dengan nama dan kemampuan berenang
-- TODO: Panggil eat(), diwarisi dari Animal
-- TODO: Panggil chirp(), method milik Bird sendiri
-- TODO: Panggil swim() hanya jika burung dapat berenang
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Konsep "Self"
Tabel dengan Fungsi'self' EksplisitSintaks Titik DuaTitik vs Titik DuaRangkuman, Titik Bergerak4Proyek: Bank Digital
Penyiapan Proyekmethod Setoran7Polimorfisme & Overriding
Menimpa methodMemanggil method indukDuck TypingAntarmuka UmumMemeriksa TipeRingkasan: Peran Karyawan10Proyek: Pengelola Bentuk
Penyiapan Proyekclass Rectangleclass Circlemethod KelilingKumpulan BentukLuas TotalSaring Bentuk2Pola Prototype untuk class
Konsep PrototypeMenghubungkan dengan __indexKonstruktor :new()Menginisialisasi AtributInstans yang MandiriRangkuman: Pabrik Mobil5Pembebanan Operator dalam OOP
Menjumlahkan ObjekMengurangkan ObjekMenggabungkan ObjekMembandingkan Objek (<, >)Ulasan: Aritmetika Dompet8Enkapsulasi
Konvensi PenamaanClosure untuk PrivasiAkses melalui ClosureTabel Hanya-BacaLogika ValidasiRangkuman: Brankas Aman11Pola Desain (Ringan)
Fungsi FactoryTabel SingletonPola IteratorObserver (Listener)Rangkuman, Factory Logger3State dan Behavior pada object
Variabel InstansGetter methodSetter methodProperty TerhitungMemformat stringPemeriksaan KesetaraanRangkuman: Nilai Siswa6Dasar-Dasar Pewarisan
Menyiapkan PewarisanMewarisi methodMemperluas KonstruktorMenambahkan method untuk ChildSama vs UnikRangkuman: Hierarki Bentuk9Komposisi & Mixins
Hubungan Has-ADelegasiMixins SederhanaMenerapkan Beberapa MixinsMixins vs PewarisanRangkuman: Perakitan RobotLatihan sendiri: Compiler Lua online