Constructor'ı Genişletme
Coddy'nin Lua Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 33 / 70.
Bir alt sınıf bir üst sınıftan miras aldığında, genellikle alt sınıfın constructor'ının (yapıcısının), üst sınıfın başlatacağı her şeyin yanı sıra alt sınıfa özgü ek alanları da ilklendirmesini istersiniz. Kod tekrarı yapmak yerine, üst sınıfın constructor'ını doğrudan çağırabilirsiniz.
Bu teknik, üst sınıf adını kullanarak onun :new() metodunu çağırmayı ve ilk argüman olarak self değerini geçirmeyi içerir. Bu, tüm üst sınıf başlatmalarıyla birlikte temel nesneyi oluşturur ve ardından bunu alt sınıf için özelleştirirsiniz.
local Vehicle = {}
Vehicle.__index = Vehicle
function Vehicle:new(speed)
local obj = {speed = speed}
setmetatable(obj, Vehicle)
return obj
end
-- Car, Vehicle'dan miras alır
local Car = {}
Car.__index = Car
setmetatable(Car, {__index = Vehicle})
function Car:new(speed, brand)
local obj = Vehicle.new(Vehicle, speed) -- Üst sınıf kurucusunu çağır
obj.brand = brand -- Alt sınıfa özgü alan ekle
setmetatable(obj, Car) -- Car'a yeniden bağla
return obj
endAlt sınıf yapıcı metodundaki (child constructor) temel adımlara dikkat edin: İlk olarak, speed alanı halihazırda ayarlanmış bir nesne elde etmek için Vehicle.new(Vehicle, speed) çağrısını yaparız. Ardından, alt sınıfa özgü brand alanını ekleriz. Son olarak, örneğin (instance) metotları önce alt sınıfta araması için metatabloyu Vehicle yerine Car olarak değiştiririz.
Üst sınıf kurucusunu çağırırken iki nokta üst üste sözdizimini de kullanabilirsiniz — Vehicle:new(speed), her ikisi de ilk argüman olarak Vehicle değerini geçirdiği için Vehicle.new(Vehicle, speed) ile eşdeğerdir. Her iki form da burada doğru şekilde çalışır, bu nedenle hangisini daha okunabilir buluyorsanız onu kullanmaktan çekinmeyin.
local myCar = Car:new(120, "Toyota")
print(myCar.speed) -- Çıktı: 120
print(myCar.brand) -- Çıktı: ToyotaBu desen kodunuzu DRY tutar; paylaşılan başlatma mantığı ebeveynde (parent) yer alırken, her bir çocuk (child) yalnızca kendi benzersiz özniteliklerini işler.
Görev
KolayBir çocuk sınıfın ebeveyn sınıfının yapıcısını (constructor) genişlettiği bir yaratık hiyerarşisi oluşturalım! Bir Animal ebeveyn sınıfı ve bir Bird çocuk sınıfı oluşturacaksınız; burada Bird'ün yapıcısı, kendi benzersiz özniteliğini eklemeden önce paylaşılan başlatma işlemlerini yönetmek için Animal'ın yapıcısını çağıracak.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
Animal.lua: Hayvanın adını saklayan bir:new(name)yapıcısı ile ebeveyn sınıfınızı tanımlayın. Hayvanın adını yazdıran bir:describe()metodu ekleyin.__indexile standart sınıf desenini kurun ve sınıfı döndürün.Bird.lua: Animal sınıfından miras alan çocuk sınıfınızı tanımlayın. Bird sınıfının:new(name, wingspan)yapıcısı, adı başlatmak içinAnimal.new(Animal, name)kullanarak ebeveyn yapıcısını çağırmalı, ardından nesneyewingspanalanını eklemeli ve son olarak metatabloyu tekrar Bird'e bağlamalıdır. Hem adı hem de kanat açıklığını belirli bir formatta yazdıran bir:info()metodu ekleyin.main.lua: Bird modülünüzü dahil edin (require), iki girdi (ad ve kanat açıklığı) okuyun, bir Bird örneği oluşturun ve miras alınan ve çocuğa özgü işlevlerin birlikte çalıştığını göstermek için her iki metodu da çağırın.
İki girdi alacaksınız:
- Kuşun adı
- Kuşun kanat açıklığı (bir sayı)
Ana dosyanızda, verilen ad ve kanat açıklığı ile bir Bird oluşturun. Ardından ayrı satırlarda önce :describe(), sonra :info() metodunu çağırın.
:describe() metodu (Animal'dan miras alınan) şunu yazdırmalıdır:
Animal: {name}:info() metodu (Bird içinde tanımlanan) şunu yazdırmalıdır:
{name} has a wingspan of {wingspan}Örneğin, girdiler Eagle ve 200 ise, çıktı şöyle olmalıdır:
Animal: Eagle
Eagle has a wingspan of 200Buradaki kilit nokta, Bird yapıcınızın ad başlatma işlemini tekrarlamamasıdır; bu işi Animal'ın yapıcısına devreder ve ardından yalnızca kuşlara özgü olanı ekler. Bu, uygun bir miras zinciri oluştururken kodunuzu DRY (Don't Repeat Yourself) tutar!
Kendin dene
-- main.lua: Giriş noktası
local Bird = require('Bird')
-- Girdileri oku
local name = io.read()
local wingspan = tonumber(io.read())
-- TODO: Verilen name ve wingspan ile bir Bird örneği oluşturun
-- TODO: Kuş üzerinde :describe() metodunu çağırın (Animal sınıfından miras alınan)
-- TODO: Kuş üzerinde :info() metodunu çağırın (Bird sınıfında tanımlanan)
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1'Self' Kavramı
Fonksiyonlu TablolarAçık 'self'İki Nokta SözdizimiNokta vs İki NoktaÖzet - Hareket Eden Nokta4Proje: Dijital Banka
Proje KurulumuPara Yatırma Metodu7Çok Biçimlilik ve Geçersiz Kılma
Metotları Geçersiz KılmaÜst Sınıf Metotlarını ÇağırmaDuck TypingOrtak ArayüzTür KontrolüÖzet - Çalışan Rolleri2Sınıf Prototip Kalıbı
Prototip Kavramı__index ile Bağlama:new() KurucusuÖznitelikleri BaşlatmaBağımsız ÖrneklerÖzet - Araba Fabrikası5OOP'de Operatör Aşırı Yükleme
Nesneleri ToplamaNesneleri ÇıkarmaNesneleri BirleştirmeNesneleri Karşılaştırma (<, >)Özet - Cüzdan Matematiği8Kapsülleme
Adlandırma KurallarıGizlilik için Closure'larClosure'lar Aracılığıyla ErişimSalt Okunur TablolarDoğrulama MantığıÖzet - Güvenli Kasa11Tasarım Kalıpları (Lite)
Fabrika FonksiyonlarıSingleton TablosuIterator KalıbıObserver (Dinleyici)Özet - Logger Fabrikası3Nesne Durumu ve Davranışı
Örnek DeğişkenleriGetter MetotlarıSetter MetotlarıHesaplanmış ÖzelliklerString BiçimlendirmeEşitlik KontrolleriÖzet - Öğrenci Notu6Kalıtımın Temelleri
Kalıtım KurulumuMetot KalıtımıConstructor'ı GenişletmeAlt Sınıf Metotları EklemePaylaşılan ve BenzersizÖzet - Şekil Hiyerarşisi