29. Pewarisan secara mendalam
Bab 27 sudah menyinggung pewarisan: satu class yang
dibangun di atas class lain. Inilah cara menghindari penulisan kode yang
sama dua kali. Dog dan Cat keduanya adalah
Animal — punya nama, punya cara dideskripsikan, yang
berbeda hanya suara yang mereka keluarkan. Pewarisan menulis
bagian yang sama sekali satu kali.
Class dasar
Mulai dengan class yang umum. Semua yang berlaku untuk seluruh keluarga ditulis di sini:
local Animal = {}
Animal.__index = Animal
function Animal.new(name)
local self = setmetatable({}, Animal)
self.name = name
return self
end
function Animal:describe()
print(self.name .. " is an animal.")
endClass anak yang mewarisi
Class anak mengarahkan pencariannya ke class dasar — setup dua baris dari Bab 27:
local Dog = setmetatable({}, { __index = Animal })
Dog.__index = Dog
function Dog.new(name)
local self = Animal.new(name) -- build with Animal's fields
return setmetatable(self, Dog) -- but tagged as a Dog
endDog tidak punya describe sendiri, tapi
__index di metatabelnya menunjuk ke Animal,
sehingga instance Dog bisa menemukannya di sana:
local rex = Dog.new("Rex")
rex:describe() -- Rex is an animal. (inherited from Animal)Pencariannya berjalan melalui rex → Dog →
Animal, berhenti di tempat pertama yang menemukan
describe.
Menambahkan perilaku yang hanya dimiliki anak
Beri class anak method yang tidak dimiliki induknya. Method ini berada di class anak, tidak terlihat oleh induk maupun saudara-saudaranya:
function Dog:fetch()
print(self.name .. " fetches the ball.")
end
rex:fetch() -- Rex fetches the ball.Overriding: mengganti method milik induk
Jika class anak mendefinisikan method dengan nama yang sama dengan milik induknya, versi anak yang ditemukan lebih dulu dan yang berlaku — ini disebut overriding:
function Dog:describe()
print(self.name .. " is a dog.")
end
rex:describe() -- Rex is a dog. (Dog's version, not Animal's)Sekarang pencarian menemukan describe di
Dog dan tidak pernah sampai ke Animal.
Memanggil versi milik induk juga
Kadang kamu ingin memperluas method induk, bukan
menggantinya: lakukan apa yang dilakukannya, lalu tambahkan sesuatu.
Panggil method induk langsung dengan namanya, dan teruskan
self:
function Dog:describe()
Animal.describe(self) -- do the Animal part first
print(" ...specifically, a dog.") -- then the Dog part
end
rex:describe()
-- Rex is an animal.
-- ...specifically, a dog.Bentuk titik Animal.describe(self) meneruskan
self secara langsung, menjalankan method milik induk pada
instance ini. "Memanggil ke atas ke induk" seperti ini adalah salah satu
alat paling berguna dalam pemrograman berorientasi objek.
Buka exercises/29/01-animals.lua. Di sana sudah ada
Animal dan Dog. Tambahkan Cat
yang mewarisi dari Animal, mengganti describe
agar menyebutkan bahwa dia adalah kucing, dan menambahkan method
meow. Buat satu kucing dan panggil keduanya.
PR
File PR ada di exercises/29/homework/.
Soal 1 — Vehicle dan Car
Buka exercises/29/homework/01-vehicle.lua. Buat class
dasar Vehicle dengan .new(name) dan
:describe() yang mencetak
<name> is a vehicle.. Kemudian buat Car
yang mewarisi darinya. Buat sebuah mobil dan panggil
:describe() — harusnya menggunakan method yang
diwarisi.
Soal 2 — Override
Buka exercises/29/homework/02-override.lua. Mulai dari
class Vehicle/Car, ganti
:describe() pada Car agar mencetak
<name> is a car.. Pastikan Vehicle masih
mengatakan "vehicle" dan Car mengatakan "car".
Soal 3 — Perluas induk
Buka exercises/29/homework/03-extend.lua. Ganti
Car:describe() agar pertama-tama memanggil
Vehicle.describe(self), lalu mencetak baris tambahan,
It has four wheels.. Kedua baris harus muncul.
Tantangan — Dua anak
Buka exercises/29/homework/04-two-children.lua. Buat
Animal beserta dua anaknya, Bird dan
Fish. Masing-masing mengganti :move() untuk
mencetak cara mereka bergerak (flies, swims).
Buat satu dari masing-masing, masukkan ke dalam sebuah daftar, dan
lakukan perulangan memanggil :move().
Mentok atau sudah selesai? Buka halaman solusi PR.