Menu
Coddy logo textTech

__newindex 메타메소드

Coddy Lua 여정의 Logic & Flow 섹션에 포함된 레슨 — 54개 중 19번째.

여러분은 __index가 테이블에 존재하지 않는 키를 읽으려고 할 때 어떤 일이 일어나는지 제어하는 방법을 배웠습니다. 이제 그 짝꿍인 __newindex를 알아볼 것입니다. 이것은 키-값 쌍을 추가하거나 수정하려고 할 때 어떤 일이 일어나는지 제어합니다.

__newindex 메타메소드는 테이블에 현재 존재하지 않는 키에 값을 할당하려고 할 때마다 트리거됩니다. 이를 통해 수정이 실제로 발생하기 전에 이를 가로채고 제어할 수 있는 권한을 갖게 됩니다.

다음은 테이블에 새로운 키가 추가되는 것을 방지하는 간단한 예제입니다:

local readOnly = {}
local meta = {
    __newindex = function(table, key, value)
        print("Cannot add key: " .. key)
    end
}

setmetatable(readOnly, meta)

readOnly.name = "Alice"  -- 출력: Cannot add key: name
print(readOnly.name)     -- 출력: nil

readOnly.name = "Alice"를 설정하려고 하면, Lua는 name이 테이블에 존재하지 않는다는 것을 확인합니다. 그것을 추가하는 대신, Lua는 세 개의 인자(테이블 자체, 설정하려는 키, 할당하려는 값)와 함께 __newindex 함수를 호출합니다.

이 예제에서 함수는 단순히 메시지를 출력하며 실제로 아무것도 저장하지 않습니다.

__newindex를 사용하여 데이터를 테이블에 허용하기 전에 유효성을 검사할 수도 있습니다:

local player = {}
local meta = {
    __newindex = function(t, key, value)
        if key == "health" and type(value) ~= "number" then
            print("Health must be a number!")
        else
            rawset(t, key, value)
        end
    end
}

setmetatable(player, meta)

player.health = "high"  -- 출력: Health must be a number!
player.health = 100     -- 허용됨

두 번째 예제에서 rawset()의 사용에 주목하세요. 이 함수는 메타테이블을 우회하여 테이블에 값을 직접 설정합니다.

그것이 없다면, 값을 설정할 때 __newindex가 다시 호출되어 무한 루프가 발생할 것입니다.

challenge icon

챌린지

쉬움

새로운 키에 대해 문자열 값만 허용하는 테이블을 반환하는 createValidatedTable 함수를 작성하세요. 이 함수는 keyvalue를 인자로 받습니다.

빈 테이블을 생성하고, 값의 타입을 검증하는 __newindex가 포함된 메타테이블을 연결하세요. 만약 누군가 문자열이 아닌 값을 추가하려고 하면, rawset()을 사용하여 "invalid"라는 문자열을 대신 저장하세요. 문자열 값인 경우에는 rawset()을 사용하여 정상적으로 저장합니다.

로직:

  • 빈 테이블을 생성합니다.
  • 테이블, 키, 값을 전달받는 __newindex가 포함된 메타테이블을 생성합니다.
  • __newindex 내부에서 type(value) == "string"을 사용하여 값이 문자열인지 확인합니다.
  • 문자열인 경우, rawset(t, key, value)를 사용하여 저장합니다.
  • 문자열이 아닌 경우, rawset(t, key, "invalid")를 사용하여 "invalid"를 대신 저장합니다.
  • setmetatable()을 사용하여 메타테이블을 테이블에 연결합니다.
  • rawset()을 사용하여 초기 키-값 쌍을 테이블에 추가합니다 (메타테이블을 우회함).
  • 테이블을 반환합니다.

매개변수:

  • key (string): 테이블에 추가할 초기 키
  • value (string): 테이블에 추가할 초기 값

반환값: 초기 키-값 쌍을 포함하며, 문자열 값만 허용하는 검증 기능이 있는 테이블 (table)

치트 시트

__newindex 메타메소드는 테이블에 존재하지 않는 키에 값을 할당하려고 할 때 트리거되어, 수정을 가로채고 제어할 수 있게 해줍니다.

새로운 키 추가를 방지하는 기본 예제:

local readOnly = {}
local meta = {
    __newindex = function(table, key, value)
        print("Cannot add key: " .. key)
    end
}

setmetatable(readOnly, meta)

readOnly.name = "Alice"  -- 출력: Cannot add key: name
print(readOnly.name)     -- 출력: nil

__newindex 함수는 테이블 자체, 설정하려는 키, 그리고 할당하려는 값의 세 가지 인수를 받습니다.

__newindex를 사용하여 데이터 유효성 검사하기:

local player = {}
local meta = {
    __newindex = function(t, key, value)
        if key == "health" and type(value) ~= "number" then
            print("Health must be a number!")
        else
            rawset(t, key, value)
        end
    end
}

setmetatable(player, meta)

player.health = "high"  -- 출력: Health must be a number!
player.health = 100     -- 허용됨

메타테이블을 우회하고 테이블에 직접 값을 설정하려면 rawset(t, key, value)를 사용하세요. 이는 __newindex 내부에서 값을 설정할 때 무한 루프가 발생하는 것을 방지합니다.

직접 해보기

function createValidatedTable(key, value)
    -- 여기에 코드를 작성하세요
end
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Logic & Flow의 모든 레슨