Delegasyon
Coddy'nin Lua Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 50 / 70.
Bir nesneyi başka bir nesnenin içinde saklamak sadece ilk adımdır. Kompozisyonun gerçek gücü delegasyondan gelir; yani dış nesne, metot çağrılarını iç bileşenlerine ilettiğinde.
Bir arabayı çalıştırmayı düşünün. Kaputun altına uzanıp motoru manuel olarak döndürmezsiniz. Bunun yerine anahtarı çevirirsiniz ve araba geri kalanını dahili olarak halleder.
Kod içerisinde bu, Car sınıfının, asıl işi motora devreden basit bir :start() metodu sağladığı anlamına gelir:
function Car:start()
print("Turning the key...")
self.engine:run() -- İç nesneye devret
endArabanın motorun nasıl çalıştığını bilmesine gerek yoktur; sadece motora işini yapmasını söyler. Bu, sorumlulukları ayrı tutar. Engine sınıfı motor mantığını yönetirken, Car parçaları koordine eder:
function Engine:run()
print("Engine running at " .. self.horsepower .. " HP")
end
local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Çıktı:
-- Anahtar çevriliyor...
-- Motor 250 HP gücünde çalışıyorDelegasyon, sınıfınızın kullanıcıları için temiz bir arayüz oluşturur. Kullanıcılar arabanın iç parçalarıyla değil, arabanın kendisiyle etkileşime girer. Daha sonra farklı bir motor uygulamasıyla değiştirseniz bile, arabanın genel arayüzü aynı kalır; yalnızca dahili delegasyon değişir.
Görev
KolayDelegasyonu gösteren bir müzik çalar sistemi kuralım! Bir Speaker bileşeni ve onu içeren bir MusicPlayer oluşturacaksınız. Çalar, ses çıkışını doğrudan yönetmeyecek; bunun yerine bu sorumluluğu dahili hoparlörüne (speaker) devredecek (delegate).
Kodunuzu üç dosya halinde düzenleyeceksiniz:
Speaker.lua: Ses seviyesini saklayan bir:new(volume)yapıcı metoduna (constructor) sahip bir Speaker sınıfı oluşturun. Şunu yazdıran bir:playSound(trackName)metodu ekleyin:Playing "{trackName}" at volume {volume}MusicPlayer.lua: Yapıcı metodu:new(brand, speaker)bir marka adı ve bir Speaker nesnesi kabul eden bir MusicPlayer sınıfı oluşturun. Çalar, hoparlörü kendi içinde saklar. Şu metodları ekleyin::play(trackName)—{brand} player starting...yazdırır ve ardından hoparlörün:playSound()metoduna delege eder.:stop()—{brand} player stoppedyazdırır.
main.lua: Her şeyi bir araya getirin! Hoparlör sesi, çalar markası ve bir parça adı için girdileri okuyun. Önce bir Speaker oluşturun, ardından bunu MusicPlayer yapıcı metoduna geçirin. Çaların:play()metodunu parça adıyla çağırın, ardından:stop()metodunu çağırın.
Üç girdi alacaksınız:
- Hoparlör sesi (bir sayı)
- Müzik çalar markası (bir dize)
- Çalınacak parça adı (bir dize)
Çıktınız, çaların hoparlörüyle koordinasyonunu göstermelidir:
{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stoppedÖrneğin, girdiler 75, SoundMax ve Summer Vibes ise çıktı şöyle olmalıdır:
SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stoppedMusicPlayer'ın sesin nasıl üretileceğini bilmediğine, sadece hoparlörüne bu kısmı halletmesini söylediğine dikkat edin. İşte bu, eylem halindeki delegasyondur: dış nesne temiz bir arayüz sağlarken, iç bileşen uzmanlaşmış işi yapar!
Kopya kağıdı
Delegasyon (Delegation), bir dış nesnenin metot çağrılarını iç bileşenlerine iletmesine olanak tanıyarak sorumlulukların ayrı tutulmasını sağlar ve temiz arayüzler oluşturur.
Dış nesne, işi iç nesnelere devreden basit metotlar sağlar:
function Car:start()
print("Turning the key...")
self.engine:run() -- İç nesneye delege et
endİç nesne kendi özelleşmiş mantığını yönetir:
function Engine:run()
print("Engine running at " .. self.horsepower .. " HP")
end
local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Çıktı:
-- Turning the key...
-- Engine running at 250 HPDelegasyonun faydaları:
- Dış sınıf, iç nesnenin nasıl çalıştığını bilmek zorunda değildir
- Kullanıcılar temiz bir genel arayüz ile etkileşime girer
- İç uygulamalar, genel arayüzü değiştirmeden değiştirilebilir
Kendin dene
-- main.lua
-- Her şeyi bir araya getirin!
local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')
-- Girdileri oku
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()
-- TODO: Verilen ses seviyesiyle bir Speaker oluşturun
-- TODO: Marka ve speaker ile bir MusicPlayer oluşturun
-- TODO: Oynatıcının play metodunu parça adıyla çağırın
-- TODO: Oynatıcının stop metodunu çağırın
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming 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ştirme