Menu
Coddy logo textTech

Domknięcia dla prywatności

Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 44 z 70.

Konwencje nazewnictwa sygnalizują intencję, ale w rzeczywistości nie uniemożliwiają dostępu. Każdy nadal może napisać player._health = 999 i to zadziała. Aby zapewnić prawdziwą prywatność, Lua oferuje inne podejście: przechowywanie danych w zmiennych lokalnych wewnątrz konstruktora zamiast w self.

Kluczowy wniosek jest taki, że zmienne lokalne wewnątrz funkcji są dostępne tylko w tej funkcji oraz w funkcjach zdefiniowanych wewnątrz niej. Nazywa się to domknięciem:

local Counter = {}
Counter.__index = Counter

function Counter:new()
    local count = 0  -- Naprawdę prywatna! Nie znajduje się w self.
    
    local obj = {}
    setmetatable(obj, Counter)
    return obj
end

W tym przykładzie count istnieje tylko wewnątrz funkcji :new(). Nie jest przechowywane w obj, więc nie można uzyskać do niego dostępu z zewnątrz: myCounter.count zwraca nil i nie ma pola z prefiksem podkreślenia, które można by obejść.

Zmienna count znajduje się w zakresie domknięcia. Pozostaje całkowicie ukryta przed kodem zewnętrznym. (W obecnej postaci nic jeszcze nie przechwytuje count; w następnej lekcji dodasz metody wewnątrz konstruktora, które będą ją obejmować domknięciem, dzięki czemu będzie istnieć tak długo, jak sam obiekt). W przeciwieństwie do self._count, który jest tylko uprzejmą sugestią, to podejście sprawia, że dane są naprawdę niedostępne.

Oczywiście ukryte dane są bezużyteczne, jeśli nie możesz z nimi wchodzić w interakcję. W następnej lekcji dowiesz się, jak definiować metody wewnątrz konstruktora, które mogą odczytywać i modyfikować te prywatne zmienne, zapewniając kontrolowany dostęp przy zachowaniu pełnej enkapsulacji.

challenge icon

Wyzwanie

Łatwy

Zbudujmy klasę SecretKeeper, która pokazuje prawdziwą prywatność danych za pomocą domknięć! W przeciwieństwie do konwencji z podkreśleniem z poprzedniej lekcji, to podejście sprawia, że dane są naprawdę niedostępne spoza obiektu.

Rozmieścisz swój kod w dwóch plikach:

  • SecretKeeper.lua: Utwórz klasę, w której sekret jest przechowywany w zmiennej lokalnej wewnątrz konstruktora, a nie w self. Konstruktor :new(secretValue) powinien przechowywać sekret w zmiennej lokalnej, która istnieje tylko w obrębie domknięcia. Na razie obiekt nie będzie miał żadnego sposobu dostępu do tego sekretu (to pojawi się w następnej lekcji!), ale zapisz też publiczne pole name o wartości "Keeper" w instancji, abyśmy mogli sprawdzić, czy obiekt działa.
  • main.lua: Załaduj moduł SecretKeeper i odczytaj sekret z wejścia. Utwórz instancję SecretKeeper z tym sekretem. Następnie pokaż, że sekret jest naprawdę prywatny, wypisując trzy rzeczy:
    • Pole name obiektu keeper (powinno wypisać Keeper)
    • Co się stanie, gdy spróbujesz uzyskać dostęp do keeper.secret (powinno być nil)
    • Co się stanie, gdy spróbujesz uzyskać dostęp do keeper._secret (również powinno być nil)

Otrzymasz jedno wejście:

  1. Wartość sekretu do przechowania (np. TopSecret123)

Wynikiem powinny być trzy wiersze pokazujące, że publiczne pole działa, a sekret jest całkowicie ukryty:

Name: Keeper
secret: nil
_secret: nil

Wynik będzie taki sam niezależnie od tego, jaki sekret podasz, ponieważ nie ma sposobu, aby uzyskać do niego dostęp! Zmienna lokalna wewnątrz konstruktora jest niewidoczna dla świata zewnętrznego. To dowodzi, że prywatność oparta na domknięciach zasadniczo różni się od konwencji nazewnictwa z podkreśleniem.

Na przykład, jeśli wejściem jest MyPassword, wynikiem nadal powinno być:

Name: Keeper
secret: nil
_secret: nil

Spróbuj swoich sił

-- Załaduj moduł SecretKeeper
local SecretKeeper = require('SecretKeeper')

-- Odczytaj tajną wartość z wejścia
local secretValue = io.read()

-- TODO: Utwórz instancję SecretKeeper z tajną wartością

-- TODO: Wypisz pole name obiektu keeper (format: "Name: <name>")

-- TODO: Wypisz, co się stanie przy dostępie do keeper.secret (format: "secret: <value>")

-- TODO: Wypisz, co się stanie przy dostępie do keeper._secret (format: "_secret: <value>")
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Lua online