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
endDalam 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.
Tantangan
MudahMari 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 padaself. 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 publiknameyang 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
namemilik keeper (seharusnya mencetakKeeper) - Yang terjadi saat kamu mencoba mengakses
keeper.secret(seharusnyanil) - Yang terjadi saat kamu mencoba mengakses
keeper._secret(seharusnya juganil)
- Field
Kamu akan menerima satu input:
- 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: nilOutput-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: nilCoba 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>")
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Konsep "Self"
Tabel dengan Fungsi'self' EksplisitSintaks Titik DuaTitik vs Titik DuaRangkuman, Titik Bergerak4Proyek: Bank Digital
Penyiapan Proyekmethod Setoran7Polimorfisme & Overriding
Menimpa methodMemanggil method indukDuck TypingAntarmuka UmumMemeriksa TipeRingkasan: Peran Karyawan10Proyek: Pengelola Bentuk
Penyiapan Proyekclass Rectangleclass Circlemethod KelilingKumpulan BentukLuas TotalSaring Bentuk2Pola Prototype untuk class
Konsep PrototypeMenghubungkan dengan __indexKonstruktor :new()Menginisialisasi AtributInstans yang MandiriRangkuman: Pabrik Mobil5Pembebanan Operator dalam OOP
Menjumlahkan ObjekMengurangkan ObjekMenggabungkan ObjekMembandingkan Objek (<, >)Ulasan: Aritmetika Dompet8Enkapsulasi
Konvensi PenamaanClosure untuk PrivasiAkses melalui ClosureTabel Hanya-BacaLogika ValidasiRangkuman: Brankas Aman11Pola Desain (Ringan)
Fungsi FactoryTabel SingletonPola IteratorObserver (Listener)Rangkuman, Factory Logger3State dan Behavior pada object
Variabel InstansGetter methodSetter methodProperty TerhitungMemformat stringPemeriksaan KesetaraanRangkuman: Nilai Siswa6Dasar-Dasar Pewarisan
Menyiapkan PewarisanMewarisi methodMemperluas KonstruktorMenambahkan method untuk ChildSama vs UnikRangkuman: Hierarki BentukLatihan sendiri: Compiler Lua online