Mixin'ler ve Kalıtım
Coddy'nin Lua Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 53 / 70.
Davranışları paylaşmanın iki yolunu öğrendin: kalıtım, prototip zinciri aracılığıyla bir "bir türüdür" ilişkisi oluştururken mixin'ler işlevleri doğrudan bir sınıfa kopyalar. Peki hangi yaklaşımı ne zaman kullanmalısın?
Nesneler temel bir kimliği paylaştığında kalıtımı kullan. Bir Bird, bir Animal'dır. Bird'ün :eat() veya :sleep() gibi temel hayvan davranışlarını devralması mantıklıdır. Bu ilişki kalıcıdır ve nesnenin özünde ne olduğunu tanımlar.
Nesnenin temel kimliğini tanımlamayan bir yetenek eklemek istediğinde mixins kullan.
Tüm kuşlar uçamaz: penguenler ve deve kuşları kuştur, ancak uçmazlar. Uçmak bir yetenektir; kuş olmanın tanımlayıcı bir özelliği değildir. Flyable mixin'i, uçma özelliğini tüm kuşlara zorunlu kılmadan, buna ihtiyaç duyan kuşlara eklemeni sağlar.
İki yaklaşım birlikte çalışır. Burada hem Eagle hem de Penguin, Bird sınıfından miras alır ve mixin'i yalnızca Eagle alır:
-- Bird, Animal sınıfından kalıtım alır (bir tür ilişkisidir)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})
-- Eagle ve Penguin, ikisi de kuştur
local Eagle = setmetatable({}, {__index = Bird})
Eagle.__index = Eagle
local Penguin = setmetatable({}, {__index = Bird})
Penguin.__index = Penguin
-- Flyable bir yetenektir (mixin)
local Flyable = {}
function Flyable:fly()
print(self.name .. " soars through the sky!")
end
-- mixin'i yalnızca uçan kuşlara uygula
applyMixin(Eagle, Flyable)Bir kartal :fly() çağırabilir. Bir penguen çağıramaz: fly, Penguin, Bird veya Animal içinde bulunmadığından penguin:fly() bir hatadır. Bunun yerine mixin'i Bird'e uygulamak, fly'ı penguenler de dahil olmak üzere tüm kuşlara kopyalardı.
Görev
KolayHadi, kalıtımın mı yoksa mixin'lerin mi ne zaman kullanılacağını gösteren küçük bir canlı ekosistemi oluşturalım! Bir Animal temel sınıfı, ondan kalıtım alan bir Bird ve bir Swimmable mixin'i oluşturacaksın; çünkü tüm kuşlar hayvan olsa da tüm kuşlar yüzemez.
Kodunu dört dosyaya ayıracaksın:
Animal.lua: Adı saklayan:new(name)kurucusuna sahip temel Animal sınıfını oluştur.{name} is eatingçıktısını veren bir:eat()yöntemi ekle. Bu, tüm hayvanların paylaştığı temel kimliği temsil eder.Swimmable.lua:{self.name} is swimmingçıktısını veren bir:swim()yöntemine sahip mixin oluştur. Bu bir yetenektir; tüm canlılar yüzemediğinden kalıtım zincirinin parçası olmamalıdır.Bird.lua: Animal sınıfından kalıtım alan bir Bird sınıfı oluştur.:new(name)kurucusu üst sınıfın kurucusunu çağırmalıdır.{name} chirps!çıktısını veren bir:chirp()yöntemi ekle. Bu, kuşlara özgü bir davranıştır. Yüzme özelliğini Bird sınıfına ekleme: her kuş yüzemez.main.lua: Mixin'in tüm işlevlerini hedefe kopyalayanapplyMixin(target, mixin)yardımcı işlevini burada yaz. Kuşun adını ve yüzüp yüzemediğini (yesveyano) oku. Bir Bird oluştur ve yüzebiliyorsa Swimmable mixin'ini yalnızca o kuşa uygula. Ardından:eat()(Animal sınıfından kalıtılan) ve:chirp()(Bird sınıfının kendi yöntemi) yöntemlerini çağır;:swim()yöntemini ise yalnızca bu kuşta varsa çağır (if bird.swim then).
İki girdi alacaksın:
- Kuşun adı (bir metin)
- Kuşun yüzüp yüzemediği:
yesveyano
Kuş yüzebiliyorsa çıktın şöyle olmalıdır:
{name} is eating
{name} chirps!
{name} is swimmingKuş yüzemiyorsa çıktın şöyle olmalıdır:
{name} is eating
{name} chirps!Örneğin, girdiler Duck ve yes ise çıktı şöyle olmalıdır:
Duck is eating
Duck chirps!
Duck is swimmingGirdiler Sparrow ve no ise çıktı şöyle olmalıdır:
Sparrow is eating
Sparrow chirps!Bu alıştırma temel farkı gösterir: Bird bir Animal'dır (kalıtım), ancak yüzme isteğe bağlı bir yetenektir (mixin). Mixin yalnızca yüzebilen kuşlara eklendiği için yüzemeyen bir kuşta swim yöntemi hiç bulunmaz.
Kendin dene
-- main.lua: Giriş noktası - bir kuş oluştur ve yeteneklerini göster
-- Bir sınıfa veya tek bir nesneye mixin uygulamak için yardımcı fonksiyon
local function applyMixin(target, mixin)
-- TODO: mixin içindeki tüm fonksiyonları target içine kopyala
end
local Bird = require('Bird')
local Swimmable = require('Swimmable')
-- Girdileri oku
local name = io.read()
local canSwimInput = io.read()
-- TODO: Verilen adla bir Bird örneği oluştur
-- TODO: Girdi "yes" ise Swimmable mixin öğesini yalnızca bu kuşa uygula
-- TODO: eat() fonksiyonunu çağır - Animal sınıfından miras alınmıştır
-- TODO: chirp() fonksiyonunu çağır - Bird sınıfının kendi metodu
-- TODO: swim() fonksiyonunu yalnızca bu kuşta varsa çağır
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şisi9Kompozisyon ve Mixin'ler
Has-A İlişkisiDelegasyonBasit Mixin'lerBirden Fazla Mixin UygulamaMixin'ler ve KalıtımÖzet - Robot BirleştirmeKendi başına pratik yap: Online Lua derleyicisi