스토리텔링 개발자

[Lua] __newindex 로 할당 로직 재정의 본문

개발/Lua

[Lua] __newindex 로 할당 로직 재정의

김디트 2021. 8. 6. 22:50
728x90

개요

테이블에 값 할당을 커스텀할 때 무심코 실수할만한 부분이 있어 정리했습니다.

 

 

 

__newindex란?

테이블에 값 할당을 시도할 시 해당 키가 존재하지 않는다면 동작하는 메타테이블의 재선언 가능입니다.
[Lua] 메타 테이블(Metatable)

 

 

 

문제점

위 정의에서 문제가 되는 부분은 '해당 키가 존재하지 않는다면' 입니다.

정리하자면 해당 키 값으로 할당된 적이 없을때만 __newindex의 로직이 실행됩니다.

 

아래의 예시를 보시죠.

isVisible 키에 할당 시 내부 inner의 isVisible에도 함께 할당시키고 싶은 상황입니다.

 

보기 쉽게 정리하면 아래와 같습니다.

1. 'isVisible 할당'이라고 출력

2. 해당 테이블에 isVisible 할당

3. 해당 테이블 내의 inner 테이블에도 isVisible 할당

 

setmetatable(instance, {
    __newindex = function(t, k, v)
        if k == "isVisible" then
            print("isVisible 할당");
            rawset(t, "isVisible", v); -- 이 부분이 문제

            if t.inner then
                t.inner.isVisible = v;
            end

            return;
        end

        rawset(t, k, v);
    end
});

 

 

위와 같이 처리하면 아래와 같은 현상이 발생합니다.

 

instance.isVisible = true;
instance.isVisible = false;

 

결과창

isVisible 할당

 

 

결과창을 보면 알 수 있다시피 두 번의 할당을 시도했지만, 할당은 단 한번만 일어났습니다.

 

이는 __newindex가 바로 '해당 키값이 없을때만' 동작하기 때문입니다.

 

 

 

해결

해결 방법은 간단합니다.

 

setmetatable(instance, {
    __newindex = function(t, k, v)
        if k == "isVisible" then
            print("isVisible 할당");
            rawset(t, "saveVisible", v); -- 이 부분의 키값을 isVisible에서 saveVisible로 수정

            if t.inner then
                t.inner.isVisible = v;
            end

            return;
        end

        rawset(t, k, v);
    end,
    __index = function(t, k)
        if k == "isVisible" then -- isVisible로 saveVisible 값을 가져오기 위해
            print("isVisible 가져오기");
            k = "saveVisible";
        end

        return rawget(t, k);
    end
});


__newindex에서 다른 키로 rawset을 해버립니다.

 

즉, 원래 의도했던 isVisible 키는 늘 비어있게 만드는 방법입니다.

 

위의 방법을 사용하면 정확히 원래 사용하고자 했던 방식으로 사용할 수 있습니다.

 

instance.isVisible = true;
instance.isVisible = false;

 

결과창

isVisible 할당
isVisible 할당

 

 

 

결론

__newindex는 새로운 할당을 할 때만 호출됩니다.

그러므로 '동일한 키에 할당하는 상황'을 캐치하려면 편법이 필요합니다.

 

__newindex 내에서 키 값을 다르게 할당해서 늘 그 키가 비어있도록 처리한다면,

__index도 함께 선언해주어서 키의 값을 가져오고 할당하는 부분을 통일성있게 해줘야 합니다.

728x90

'개발 > Lua' 카테고리의 다른 글

[Lua] 상속 구조 만들기  (0) 2021.07.27
[Lua] 메타 테이블(Metatable)  (0) 2021.07.21
Comments