읽기 전용 테이블
Coddy Lua 여정의 객체 지향 프로그래밍 (Object Oriented Programming) 섹션에 포함된 레슨. 70개 중 46번째.
클로저는 진정한 비공개성을 제공하지만, 생성자 내부에 메서드를 정의해야 합니다. 다른 사용 사례를 위한 또 다른 접근 방식으로, 생성 후 객체를 읽기 전용으로 만드는 방법이 있습니다. 이는 필드를 볼 수는 있지만 변경할 수 없도록 하려는 경우에 유용합니다. 예를 들어 고정된 점의 좌표와 같은 경우입니다.
__newindex metamethod는 테이블에 새 값을 할당하려는 시도를 가로챕니다. 모든 할당을 차단하도록 만들면 object를 동결할 수 있습니다:
local ImmutablePoint = {}
function ImmutablePoint.new(x, y)
local data = {x = x, y = y}
local proxy = {}
setmetatable(proxy, {
__index = data,
__newindex = function()
error("Cannot modify immutable object")
end
})
return proxy
end비결은 프록시 테이블을 사용하는 것입니다. 실제 데이터는 data에 저장되고, 사용자는 비어 있는 proxy와 상호 작용합니다.
읽을 때 __index는 data에서 가져옵니다. 쓸 때는 대신 __newindex가 트리거되며, 이를 차단합니다.
local p = ImmutablePoint.new(10, 20)
print(p.x) -- 10 (읽기 작동)
p.x = 50 -- Error: 불변 객체를 수정할 수 없습니다이 패턴은 configuration object, 수학 상수 또는 초기화 후 절대 변경되지 않아야 하는 모든 data에 유용합니다. object는 완전히 읽을 수 있는 상태로 유지됩니다. 단지 이를 변경할 수 없을 뿐입니다.
챌린지
쉬움ImmutableConfig class를 만들어 읽기 전용 구성 객체를 생성해 봅시다! 한 번 생성된 이러한 config 객체는 설정을 읽을 수 있게 해야 하지만, 수정하려는 모든 시도는 완전히 차단해야 합니다.
코드를 두 개의 파일로 구성합니다:
ImmutableConfig.lua: 동결된 구성 객체를 생성하는 module을 만드세요..new(appName, version, maxUsers)function은 이 세 값을 내부에 저장한 다음, 모든 field를 읽을 수 있지만 어떤 modifications도 방지하는 프록시 테이블을 반환해야 합니다. 누군가 값을 변경하려고 하면 실제 error를 발생시키는 대신Error: Config is read-only를 print해야 합니다.main.lua: ImmutableConfig을 실제로 사용해 봅시다! 구성 값에 대한 세 가지 입력을 읽고 config 객체를 생성한 다음, 다음과 같이 올바르게 작동하는지 보여 주세요:- 세 가지 original 값을 모두 print
maxUsersfield 수정을 시도합니다(이때 error message가 표시되어야 함)- 값이 실제로 changed되지 않았음을 증명하기 위해
maxUsers를 다시 print
세 가지 입력을 받습니다:
- application 이름(string)
- version(string)
- maximum 사용자 수(number)
출력에는 config 값, modification 시도 시의 error, 그리고 값이 변경되지 않은 채로 유지되었다는 확인이 표시되어야 합니다:
App: {appName}
Version: {version}
Max Users: {maxUsers}
Error: Config is read-only
Max Users: {maxUsers}예를 들어 입력이 MyApp, 2.0, 100인 경우 출력은 다음과 같아야 합니다:
App: MyApp
Version: 2.0
Max Users: 100
Error: Config is read-only
Max Users: 100기억하세요. 프록시 패턴은 사용자가 상호 작용하는 empty 테이블을 사용하는 반면, actual data는 별도의 internal 테이블에 저장됩니다. __index metamethod는 data 테이블에서 값을 가져오고, __newindex는 모든 쓰기 시도를 가로채서 차단합니다!
직접 해보기
-- ImmutableConfig 모듈을 가져옵니다
local ImmutableConfig = require('ImmutableConfig')
-- 입력을 읽습니다
local appName = io.read()
local version = io.read()
local maxUsers = tonumber(io.read())
-- TODO: ImmutableConfig.new()를 사용하여 config 객체를 생성합니다
-- TODO: 다음 형식으로 세 개의 원래 값을 모두 출력합니다:
-- App: {appName}
-- Version: {version}
-- Max Users: {maxUsers}
-- TODO: maxUsers 필드를 수정하려고 시도합니다 (이렇게 하면 오류 메시지가 발생해야 합니다)
-- TODO: 변경되지 않았음을 증명하기 위해 maxUsers를 다시 출력합니다
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍 (Object Oriented Programming)의 모든 레슨
직접 연습해 보세요: 온라인 Lua 컴파일러