루아에서 `__newindex` 메타메서드는 어떻게 사용하나요?
_____A: `__newindex`는 테이블에 존재하지 않는 필드에 값을 할당할 때 호출되는 메타메서드입니다. 즉, 새 키-값 쌍을 테이블에 추가할 때 동작하는 특별한 함수입니다.
Q: `__newindex` 메타메서드는 언제 호출되나요?
A: 테이블에 없는 키에 대해 값을 새로 저장하려 할 때 호출됩니다. 만약 해당 키가 이미 존재하면 `__newindex`는 호출되지 않고 직접 값이 변경됩니다.
Q: `__newindex`는 어떻게 설정하나요?
A: 메타테이블(metatable)에 `__newindex` 필드로 함수나 다른 테이블을 지정해서 설정합니다. 예:
```lua
local t = {}
local mt = {
__newindex = function(table, key, value)
print("Adding new key", key, "with value", value)
rawset(table, key, value) -- 값 할당
end
}
setmetatable(t, mt)
t.someKey = 123 -- __newindex 호출
```
Q: `__newindex`에 함수가 아닌 테이블을 지정하면 어떻게 되나요?
A: 새로운 키를 할당할 때 원래 테이블 대신 이 메타테이블의 `__newindex`로 지정된 테이블에 값을 저장합니다. 즉,
```lua
local proxy = {}
local t = {}
setmetatable(t, {__newindex = proxy})
t.foo = 42 -- proxy["foo"] = 42와 동일한 효과
print(proxy.foo) -- 출력 42
```
A: `__newindex` 함수 내에서 직접 `table[key] = value`라고 하면 무한 재귀가 발생합니다. 따라서 `rawset(table, key, value)`를 사용해야 합니다.
```lua
__newindex = function(table, key, value)
rawset(table, key, value)
end
```
Q: `__newindex`를 이용한 활용 예시는 무엇인가요?
A:
- 필드 추가를 감시해 로그를 출력하거나 검증
- 읽기 전용 테이블을 만들어 쓰기 시도를 차단
- 프로퍼티 스타일 엑세스 구현
- 프록시 테이블 구현 등
Q: 예시 - 쓰기 시도 차단하는 `__newindex` 구현
```lua
local t = {}
setmetatable(t, {
__newindex = function(table, key, value)
error("테이블 수정 불가")
end
})
t.x = 10 -- 에러 발생
```
Q: 정리
- `__newindex`는 없는 키에 값을 할당할 때 동작하는 메타메서드
- 메타테이블의 필드로 함수나 테이블을 지정 가능
- 함수형일 경우 재귀 방지를 위해 `rawset` 사용 필수
- 다양한 테이블 동작 제어에 활용 가능하다
이 메타메서드는 주로 테이블의 동작을 커스터마이즈하고, 특정 조건을 만족할 때만 값을 설정하거나, 값을 설정할 때 추가적인 로직을 수행하고자 할 때 사용됩니다.
기본 개념 루아에서 테이블은 기본적으로 키-값 쌍으로 데이터를 저장하는 자료구조입니다.
하지만, 테이블에 직접적으로 접근하여 값을 설정할 때, 루아는 해당 테이블의 메타테이블에 정의된 `__newindex` 메타메서드를 확인합니다.
만약 메타테이블에 `__newindex`가 정의되어 있다면, 루아는 이 메타메서드를 호출하여 값을 설정합니다.
사용 방법 1. 메타테이블 생성 : 먼저, 메타테이블을 생성하고, 그 안에 `__newindex` 메타메서드를 정의합니다.
2. 테이블에 메타테이블 설정 : 메타테이블을 사용할 테이블에 설정합니다.
3. 값 설정 : 테이블에 값을 설정할 때, `__newindex` 메타메서드가 호출됩니다.
예제 코드 아래는 `__newindex` 메타메서드를 사용하는 간단한 예제입니다.
```lua -- 메타테이블 정의 local mt = { __newindex = function(table, key, value) if type(key) == "string" then rawset(table, key, value) -- 실제 테이블에 값을 설정 print("Setting " .. key .. " to " .. tostring(value)) else error("Key must be a string") end end } -- 테이블 생성 local myTable = {} -- 메타테이블 설정 setmetatable(myTable, mt) -- 값 설정 myTable.name = "Lua" -- __newindex가 호출되어 "Setting name to Lua" 출력 myTable.age = 5 -- __newindex가 호출되어 "Setting age to 5" 출력 -- 잘못된 키 사용 -- myTable[1] = "Invalid" -- 에러 발생: Key must be a string ``` 설명 1. 메타테이블 정의 : `mt`라는 메타테이블을 정의하고, `__newindex` 메타메서드를 구현합니다.
이 메타메서드는 키가 문자열인지 확인하고, 문자열일 경우에만 값을 설정합니다.
그렇지 않으면 에러를 발생시킵니다.
2. 테이블 생성 및 메타테이블 설정 : `myTable`이라는 테이블을 생성하고, `setmetatable` 함수를 사용하여 `mt`를 메타테이블로 설정합니다.
3. 값 설정 : `myTable.name`과 `myTable.age`에 값을 설정할 때, `__newindex` 메타메서드가 호출되어 설정된 값과 함께 메시지를 출력합니다.
만약 잘못된 키(예: 숫자)를 사용하면 에러가 발생합니다.
활용 사례 - 유효성 검사 : 특정 조건을 만족하는 경우에만 값을 설정하도록 하여 데이터의 무결성을 유지할 수 있습니다.
- 로그 기록 : 값이 설정될 때마다 로그를 기록하여 디버깅에 도움을 줄 수 있습니다.
- 자동 변환 : 값을 설정할 때 자동으로 형 변환을 수행할 수 있습니다.
결론 루아의 `__newindex` 메타메서드는 테이블에 값을 설정할 때의 동작을 커스터마이즈할 수 있는 강력한 도구입니다.
이를 통해 데이터의 유효성을 검사하거나, 특정 로직을 추가하여 테이블의 동작을 보다 유연하게 제어할 수 있습니다.
작성자:
박시우 [비회원]
| 작성일자: 1년 전
2024-12-05 19:51:39
조회수: 169 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
조회수: 169 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.