Menu
Coddy logo textTech

Closure'lar Aracılığıyla Erişim

Coddy'nin Lua Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 45 / 70.

Özel yerel değişkenler, onlarla asla etkileşime giremiyorsanız işe yaramazlar. Çözüm, getter ve setter metotlarını, closure kapsamına (scope) erişebildikleri constructor'ın içinde tanımlamaktır.

Bu metotlar :new() içinde oluşturulduğu için yerel değişkenleri "görebilirler". Onları doğrudan nesneye atarsınız:

local Counter = {}
Counter.__index = Counter

function Counter:new()
    local count = 0  -- Özel değişken
    
    local obj = {}
    
    -- Metotları yapıcı (constructor) içinde tanımlayın
    function obj:getCount()
        return count
    end
    
    function obj:increment()
        count = count + 1
    end
    
    setmetatable(obj, Counter)
    return obj
end

Artık özel count değişkenine erişilebilir—ancak yalnızca sağladığınız yöntemler aracılığıyla:

local c = Counter:new()
print(c:getCount())  -- 0
c:increment()
c:increment()
print(c:getCount())  -- 2
print(c.count)       -- nil (hâlâ gizli!)

:getCount() ve :increment() fonksiyonlarının sınıf tablosunda değil, doğrudan obj üzerinde tanımlandığına dikkat edin. Her örnek bu fonksiyonların kendi kopyasını alır ve her biri kendi özel count değişkenine erişebilir. Bu bir ödünleşimdir: Metotlar prototip aracılığıyla paylaşılmadığı için gerçek gizlilik biraz daha fazla bellek maliyeti gerektirir.

challenge icon

Görev

Kolay

Kontrollü erişim sağlamak için yapıcı (constructor) içinde tanımlanmış getter ve setter metotlarıyla, Celsius cinsinden bir sıcaklık değerini saklamak için closure tabanlı gizlilik kullanan bir Temperature sınıfı oluşturalım!

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • Temperature.lua: Sıcaklık değerinin yapıcı içinde yerel bir değişkende saklandığı ve dış erişime tamamen kapalı olduğu bir sınıf oluşturun. :new(initialCelsius) yapıcısı, sıcaklığı yerel bir değişkende saklamalı ve ardından şu metotları doğrudan nesne örneği üzerinde tanımlamalıdır:
    • :getCelsius() — Celsius cinsinden mevcut sıcaklığı döndürür
    • :setCelsius(value) — sıcaklığı yeni bir değerle günceller
    • :getFahrenheit()(celsius * 9/5) + 32 formülünü kullanarak sıcaklığı Fahrenheit'a dönüştürülmüş olarak döndürür
  • main.lua: Temperature modülünüzü dahil edin (require) ve girdiden iki değer okuyun: bir başlangıç sıcaklığı ve ayarlanacak yeni bir sıcaklık. Başlangıç değeriyle bir Temperature örneği oluşturun, Celsius ve Fahrenheit değerlerini yazdırın, ardından sıcaklığı değiştirmek için setter'ı kullanın ve her iki değeri tekrar yazdırın.

İki girdi alacaksınız:

  1. Celsius cinsinden başlangıç sıcaklığı (bir sayı)
  2. Ayarlanacak yeni bir sıcaklık (bir sayı)

Çıktınız, değişiklikten önceki ve sonraki sıcaklık değerlerini gösteren dört satır olmalıdır:

Celsius: {initialValue}
Fahrenheit: {convertedInitial}
Celsius: {newValue}
Fahrenheit: {convertedNew}

Örneğin, girdiler 0 ve 100 ise, çıktı şöyle olmalıdır:

Celsius: 0
Fahrenheit: 32
Celsius: 100
Fahrenheit: 212

Unutmayın: sıcaklık değeri self üzerinde değil, :new() içindeki yerel bir değişkende saklanmalıdır. Getter ve setter metotları, bu özel değişkene closure aracılığıyla erişebildikleri yapıcı içinde tanımlanır. Doğrudan temp.celsius veya temp._celsius değişkenlerine erişmeye çalışmak nil döndürmelidir!

Kopya kağıdı

Lua sınıflarında gerçekten özel (private) değişkenler oluşturmak için, getter ve setter metotlarını, closure aracılığıyla yerel değişkenlere erişebildikleri yapıcı (constructor) içinde tanımlayın.

Metotlar doğrudan nesne örneğine atanır (sınıf tablosuna değil), bu da her örneğe kendi özel değişkenlerine erişimi olan kendi kopyasını verir:

local Counter = {}
Counter.__index = Counter

function Counter:new()
    local count = 0  -- Özel değişken
    
    local obj = {}
    
    -- Metotları yapıcı içinde tanımlayın
    function obj:getCount()
        return count
    end
    
    function obj:increment()
        count = count + 1
    end
    
    setmetatable(obj, Counter)
    return obj
end

Kullanım:

local c = Counter:new()
print(c:getCount())  -- 0
c:increment()
c:increment()
print(c:getCount())  -- 2
print(c.count)       -- nil (hala gizli!)

Ödünleşim (Trade-off): Her örnek metotların kendi kopyasını alır (prototip aracılığıyla paylaşılmaz), bu da daha fazla bellek kullanır ancak gerçek gizlilik sağlar.

Kendin dene

-- Temperature modülünü dahil et
local Temperature = require('Temperature')

-- Giriş değerlerini oku
local initialTemp = tonumber(io.read())
local newTemp = tonumber(io.read())

-- YAPILACAK: Başlangıç değeriyle bir Temperature örneği oluşturun

-- YAPILACAK: Başlangıçtaki Celsius ve Fahrenheit değerlerini yazdırın

-- YAPILACAK: Sıcaklığı newTemp olarak değiştirmek için ayarlayıcıyı (setter) kullanın

-- YAPILACAK: Güncellenmiş Celsius ve Fahrenheit değerlerini yazdırın
quiz iconKendini test et

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