Gizlilik için Closure'lar
Coddy'nin Lua Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 44 / 70.
Adlandırma kuralları niyeti belirtir, ancak erişimi gerçekten engellemez. Herkes hala player._health = 999 yazabilir ve bu çalışır. Gerçek gizlilik için Lua farklı bir yaklaşım sunar: verileri self yerine yapıcı (constructor) içindeki yerel değişkenlerde saklamak.
Temel içgörü, bir fonksiyonun içindeki yerel değişkenlerin yalnızca o fonksiyonun içinden ve onun içinde tanımlanan herhangi bir fonksiyondan erişilebilir olmasıdır. Buna bir closure denir:
local Counter = {}
Counter.__index = Counter
function Counter:new()
local count = 0 -- Gerçekten gizli! self üzerinde değil.
local obj = {}
setmetatable(obj, Counter)
return obj
endBu örnekte, count yalnızca :new() fonksiyonunun içinde bulunur. obj içinde saklanmaz, bu yüzden ona dışarıdan erişmenin bir yolu yoktur—myCounter.count nil döndürür ve atlanacak alt çizgi önekli bir alan yoktur.
count değişkeni closure kapsamı içinde yer alır. Dış koddan tamamen gizli kalır. (Yazıldığı haliyle, henüz hiçbir şey count değişkenini yakalamaz; bir sonraki derste, yapıcı (constructor) içine onu kapsayan metodlar ekleyeceksiniz, böylece nesne var olduğu sürece o da kalıcı olacaktır.) Sadece nazik bir öneri olan self._countun aksine, bu yaklaşım veriyi gerçekten erişilemez kılar.
Elbette, gizli verilerle hiçbir zaman etkileşime giremiyorsanız, bu veriler yararlı değildir. Bir sonraki derste, bu private değişkenleri okuyabilen ve değiştirebilen metotları constructor içinde nasıl tanımlayacağınızı öğreneceksiniz; bu da size gerçek encapsulation'ı korurken kontrollü erişim sağlar.
Görev
KolayClosure'ları kullanarak gerçek veri gizliliğini gösteren bir SecretKeeper sınıfı oluşturalım! Önceki dersteki alt çizgi kuralının aksine, bu yaklaşım verileri nesne dışından gerçekten erişilemez hale getirir.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
SecretKeeper.lua: Gizli değerinselfüzerinde değil, yapıcı (constructor) içindeki yerel bir değişkende saklandığı bir sınıf oluşturun.:new(secretValue)yapıcısı, gizli değeri yalnızca closure içinde var olan yerel bir değişkende saklamalıdır. Şimdilik, nesnenin bu gizli değere erişmek için herhangi bir yolu olmayacak (bu bir sonraki derste gelecek!), ancak nesnenin çalıştığını doğrulayabilmemiz için örnek (instance) üzerinde"Keeper"olarak ayarlanmış genel birnamealanı da saklamalısınız.main.lua: SecretKeeper modülünüzü dahil edin ve girdiden bir gizli değer okuyun. Bu gizli değerle bir SecretKeeper örneği oluşturun. Ardından üç şeyi yazdırarak gizli değerin gerçekten özel olduğunu kanıtlayın:- Keeper'ın
namealanı (Keeperyazdırmalıdır) keeper.secretdeğerine erişmeye çalıştığınızda ne olduğu (nilolmalıdır)keeper._secretdeğerine erişmeye çalıştığınızda ne olduğu (bu danilolmalıdır)
- Keeper'ın
Bir girdi alacaksınız:
- Saklanacak gizli değer (örneğin,
TopSecret123)
Çıktınız, genel alan çalışırken gizli değerin tamamen gizlendiğini gösteren üç satır olmalıdır:
Name: Keeper
secret: nil
_secret: nilHangi gizli değeri girerseniz girin çıktı aynı olacaktır; çünkü ona erişmenin hiçbir yolu yoktur! Yapıcı içindeki yerel değişken dış dünyaya görünmezdir. Bu, closure tabanlı gizliliğin alt çizgi adlandırma kuralından temelden farklı olduğunu kanıtlar.
Örneğin, girdi MyPassword ise, çıktı yine şu şekilde olmalıdır:
Name: Keeper
secret: nil
_secret: nilKendin dene
-- SecretKeeper modülünü dahil edin
local SecretKeeper = require('SecretKeeper')
-- Girdiden gizli değeri okuyun
local secretValue = io.read()
-- TODO: Gizli değer ile bir SecretKeeper örneği oluşturun
-- TODO: keeper nesnesinin name alanını yazdırın (format: "Name: <name>")
-- TODO: keeper.secret değerine erişildiğinde ne olduğunu yazdırın (format: "secret: <value>")
-- TODO: keeper._secret değerine erişildiğinde ne olduğunu yazdırın (format: "_secret: <value>")
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