Mixins vs Pewarisan
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan Lua di Coddy. Pelajaran 53 dari 70.
Kamu telah mempelajari dua cara untuk berbagi perilaku: pewarisan menciptakan hubungan "adalah" melalui rantai prototipe, sedangkan mixin menyalin fungsi langsung ke dalam class. Namun, kapan kamu sebaiknya menggunakan masing-masing pendekatan?
Gunakan pewarisan saat objek memiliki identitas mendasar yang sama. Bird adalah Animal. Bird cocok mewarisi perilaku dasar hewan seperti :eat() atau :sleep(). Hubungan ini bersifat tetap dan menentukan hakikat objek 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 ciri yang menentukan bahwa sesuatu adalah burung. Mixin Flyable memungkinkanmu menambahkan kemampuan terbang pada burung yang membutuhkannya, tanpa memaksakannya pada semua burung.
Kedua pendekatan ini bekerja bersama. Di sini, Eagle dan Penguin sama-sama mewarisi Bird, dan hanya Eagle yang mendapatkan mixin:
-- Bird mewarisi Animal (hubungan is-a)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})
-- Eagle dan Penguin sama-sama burung
local Eagle = setmetatable({}, {__index = Bird})
Eagle.__index = Eagle
local Penguin = setmetatable({}, {__index = Bird})
Penguin.__index = Penguin
-- 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(Eagle, Flyable)Elang dapat memanggil :fly(). Penguin tidak bisa: fly tidak ada di Penguin, Bird, atau Animal, jadi penguin:fly() adalah error. Menerapkan mixin ke Bird justru akan menyalin fly ke setiap burung, termasuk penguin.
Tantangan
MudahMari buat ekosistem kecil berisi makhluk yang menunjukkan kapan kamu sebaiknya menggunakan pewarisan dibandingkan mixin! Kamu akan membuat class dasar Animal, Bird yang mewarisi class tersebut, dan mixin Swimmable, karena meskipun semua burung adalah hewan, tidak semua burung bisa berenang.
Kamu akan mengatur kodemu di 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 tidak seharusnya menjadi bagian dari rantai pewarisan.Bird.lua: Buat class Bird yang mewarisi Animal. Konstruktor:new(name)harus memanggil konstruktor induk. Sertakan method:chirp()yang mencetak{name} chirps!. Ini adalah perilaku khusus burung. Jangan masukkan kemampuan berenang ke Bird, karena tidak semua burung bisa berenang.main.lua: Tulis helperapplyMixin(target, mixin)di sini. Helper ini menyalin setiap fungsi dari mixin ke target. Baca nama burung dan apakah burung itu bisa berenang (yesatauno). Buat sebuah Bird, lalu jika burung itu bisa berenang, terapkan mixin Swimmable hanya pada burung tersebut. Kemudian panggil:eat()(diwarisi dari Animal) dan:chirp()(method milik Bird), lalu panggil:swim()hanya jika burung ini memilikinya (if bird.swim then).
Kamu akan menerima dua input:
- Nama burung (sebuah string)
- Apakah burung itu bisa berenang:
yesatauno
Jika burung itu bisa berenang, output-mu seharusnya seperti berikut:
{name} is eating
{name} chirps!
{name} is swimmingJika burung itu tidak bisa berenang, output-mu seharusnya seperti berikut:
{name} is eating
{name} chirps!Contohnya, jika input-nya adalah Duck dan yes, output-nya seharusnya seperti berikut:
Duck is eating
Duck chirps!
Duck is swimmingJika input-nya adalah Sparrow dan no, output-nya seharusnya seperti berikut:
Sparrow is eating
Sparrow chirps!Tantangan ini menunjukkan perbedaan utamanya: Bird adalah seekor Animal (pewarisan), tetapi berenang adalah kemampuan opsional (mixin). Karena mixin hanya diterapkan pada burung yang bisa berenang, burung yang tidak bisa berenang sama sekali tidak memiliki method swim.
Coba sendiri
-- main.lua: Titik masuk, buat seekor burung dan tunjukkan kemampuannya
-- Fungsi pembantu untuk menerapkan mixin ke class atau satu object
local function applyMixin(target, mixin)
-- TODO: Salin setiap fungsi dari mixin ke target
end
local Bird = require('Bird')
local Swimmable = require('Swimmable')
-- Baca input
local name = io.read()
local canSwimInput = io.read()
-- TODO: Buat instance Bird dengan nama tersebut
-- TODO: Jika input adalah "yes", terapkan mixin Swimmable hanya ke burung ini
-- TODO: Panggil eat(), yang diwarisi dari Animal
-- TODO: Panggil chirp(), method milik Bird sendiri
-- TODO: Panggil swim() hanya jika burung ini memilikinya
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