Menu
CoddyTech

Closure untuk Privasi

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan Lua di Coddy. Pelajaran 44 dari 70.

Konvensi penamaan menunjukkan maksud, tetapi sebenarnya tidak mencegah akses. Siapa pun tetap bisa menulis player._health = 999 dan kode itu akan berfungsi. Untuk privasi sejati, Lua menawarkan pendekatan lain: menyimpan data dalam variabel lokal di dalam konstruktor, bukan pada self.

Hal penting yang perlu dipahami adalah variabel lokal di dalam fungsi hanya dapat diakses di dalam fungsi tersebut dan fungsi apa pun yang didefinisikan di dalamnya. Ini disebut closure:

local Counter = {}
Counter.__index = Counter

function Counter:new()
    local count = 0  -- Benar-benar privat! Tidak ada di self.
    
    local obj = {}
    setmetatable(obj, Counter)
    return obj
end

Dalam contoh ini, count hanya ada di dalam fungsi :new(). Nilai tersebut tidak disimpan di obj, jadi tidak ada cara untuk mengaksesnya dari luar: myCounter.count menghasilkan nil, dan tidak ada field berawalan garis bawah yang bisa digunakan untuk melewati pembatasan.

Variabel count berada dalam cakupan closure. Variabel ini sepenuhnya tersembunyi dari kode eksternal. (Dalam bentuknya saat ini, belum ada yang menangkap count. Pada pelajaran berikutnya, kamu akan menambahkan method di dalam konstruktor yang menutup cakupannya, sehingga variabel ini tetap ada selama object-nya ada.) Berbeda dengan self._count, yang hanya berupa saran sopan, pendekatan ini membuat data benar-benar tidak dapat diakses.

Tentu saja, data tersembunyi tidak berguna jika kamu tidak bisa berinteraksi dengannya. Pada pelajaran berikutnya, kamu akan belajar cara mendefinisikan method di dalam constructor yang dapat membaca dan mengubah variabel privat ini, sehingga kamu bisa mengaksesnya secara terkendali sambil menjaga enkapsulasi yang sesungguhnya.

challenge icon

Tantangan

Mudah

Mari kita buat SecretKeeper class yang menunjukkan privasi data sejati menggunakan closure! Berbeda dari konvensi garis bawah pada pelajaran sebelumnya, pendekatan ini membuat data benar-benar tidak dapat diakses dari luar object.

Kamu akan mengatur kodemu dalam dua file:

  • SecretKeeper.lua: Buat class yang menyimpan rahasia dalam variabel lokal di dalam constructor, bukan pada self. Constructor :new(secretValue) harus menyimpan rahasia dalam variabel lokal yang hanya ada di dalam closure. Untuk saat ini, object tidak akan memiliki cara untuk mengakses rahasia ini (caranya akan dibahas pada pelajaran berikutnya!), tetapi kamu juga harus menyimpan field publik name yang diatur ke "Keeper" pada instance agar kita bisa memastikan object berfungsi.
  • main.lua: Impor module SecretKeeper dan baca nilai rahasia dari input. Buat instance SecretKeeper dengan rahasia tersebut. Lalu tunjukkan bahwa rahasia itu benar-benar privat dengan mencetak tiga hal:
    • Field name milik keeper (seharusnya mencetak Keeper)
    • Yang terjadi saat kamu mencoba mengakses keeper.secret (seharusnya nil)
    • Yang terjadi saat kamu mencoba mengakses keeper._secret (seharusnya juga nil)

Kamu akan menerima satu input:

  1. Nilai rahasia yang akan disimpan (misalnya, TopSecret123)

Output-mu harus terdiri dari tiga baris yang menunjukkan bahwa field publik berfungsi, sedangkan rahasia sepenuhnya tersembunyi:

Name: Keeper
secret: nil
_secret: nil

Output-nya akan tetap sama apa pun rahasia yang kamu berikan, karena tidak ada cara untuk mengaksesnya! Variabel lokal di dalam constructor tidak terlihat oleh dunia luar. Ini membuktikan bahwa privasi berbasis closure pada dasarnya berbeda dari konvensi penamaan garis bawah.

Misalnya, jika input-nya adalah MyPassword, output-nya akan tetap seperti ini:

Name: Keeper
secret: nil
_secret: nil

Coba sendiri

-- Muat module SecretKeeper dengan require
local SecretKeeper = require('SecretKeeper')

-- Baca nilai rahasia dari input
local secretValue = io.read()

-- TODO: Buat instance SecretKeeper dengan nilai rahasia

-- TODO: Cetak field name milik keeper (format: "Name: <name>")

-- TODO: Cetak apa yang terjadi saat mengakses keeper.secret (format: "secret: <value>")

-- TODO: Cetak apa yang terjadi saat mengakses keeper._secret (format: "_secret: <value>")
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler Lua online