English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Lua 테이블에서는 특정 키를 통해 값을 가져올 수 있지만, 두 테이블을 조작할 수는 없습니다.
따라서 Lua는 테이블의 행동을 변경할 수 있는 메타테이블을 제공하며, 각 행동은 해당 메타 메서드와 연결됩니다.
예를 들어, 메타테이블을 사용하여 Lua가 두 테이블의 더하기 연산을 어떻게 계산할지 정의할 수 있습니다.+b。
Lua가 두 테이블을 더하는 시도를 할 때, 먼저 두 테이블 중 하나에 메타테이블이 있는지 확인하고, 그 다음 "__add" 필드가 있는지 확인합니다. "__add"과 같은 즉시 필드의 값을 호출하면 "메타 메서드"라고 합니다. 메타 메서드의 값을 호출하면 "메타 메서드"라고 합니다.
메타테이블을 처리하는 두 가지 매우 중요한 함수가 있습니다:
setmetatable(table, metatable): 특정 테이블에 메타테이블(metatable)을 설정할 때, 메타테이블에 __metatable 키가 존재하면 setmetatable은 실패합니다.
getmetatable(table): 반환된 객체 메타테이블(metatable)
다음 예제는 특정 테이블에 메타테이블을 설정하는 방법을 보여줍니다:
mytable = {} -- 일반 테이블 mymetatable = {} -- 메타테이블 setmetatable(mytable, mymetatable) -- mymetatable을 mytable의 메타테이블로 설정합니다
위 코드는 한 줄로 직접 작성할 수도 있습니다:
mytable = setmetatable({}, {})
다음은 반환된 객체 메타테이블입니다:
getmetatable(mytable) -- 이번에는 mymetatable을 반환합니다
이것은 metatable에서 가장 자주 사용되는 키입니다.
당신이 테이블에 키를 통해 접근할 때, 그 키에 값이 없다면 Lua는 테이블의 metatable(존재하는 경우)의 __index 키를 찾습니다. 만약 __index가 테이블을 포함하고 있다면, Lua는 테이블에서 해당 키를 찾습니다.
우리는 lua 명령어를 사용하여 인터랙티브 모드로 접근할 수 있습니다:
$ lua Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio > other = { foo = 3 } > t = setmetatable({}, { __index = other }) > t.foo 3 > t.bar nil
만약 __index가 함수를 포함하고 있다면, Lua는 그 함수를 호출하고 테이블과 키를 함수의 매개변수로 전달합니다.
__index 메서드는 테이블 요소가 존재하는지 확인합니다. 존재하지 않으면 nil을 반환하고, 존재하면 __index가 결과를 반환합니다.
mytable = setmetatable({key1 = "value1"}, { __index = function(mytable, key) if key == "key2" then return "metatablevalue" else return nil end end ) print(mytable.key1,mytable.key2)
예제 출력 결과는 다음과 같습니다:
value1 metatablevalue
예제 해석:
mytable 테이블에 할당됩니다 {key1 = "value1"}。
mytable이 메타테이블을 설정했으며, 메타테이블 메서드는 __index입니다。
mytable에서 key를 검색합니다1찾으면 해당 요소를 반환하고, 찾지 못하면 계속 진행합니다。
mytable에서 key를 검색합니다2찾으면 metatablevalue를 반환하고, 찾지 못하면 계속 진행합니다。
메타테이블에 __index 메서드가 있는지 확인합니다. __index 메서드가 함수라면, 그 함수를 호출합니다.
메타테이블 메서드에서 "key" 매개변수가 전달되었는지 확인합니다2" 키 매개변수(mytable.key2이미 설정된 경우),"key" 매개변수를 전달하면2" 매개변수가 반환되면 "metatablevalue"을 반환하며, 그렇지 않으면 mytable에 해당하는 키 값을 반환합니다.
위 코드를 간단히 작성할 수 있습니다:
mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } } print(mytable.key1,mytable.key2)
정리
Lua가 테이블 요소를 찾을 때의 규칙은 다음과 같습니다: 3 단계:
1.테이블에서 검색합니다. 찾으면 해당 요소를 반환하고, 찾지 못하면 계속 진행합니다
2.테이블에 메타테이블이 있는지 확인합니다. 메타테이블이 없으면 nil을 반환합니다. 메타테이블이 있으면 계속 진행합니다.
3.메타테이블에 __index 메서드가 있는지 확인합니다. __index 메서드가 nil이면 nil을 반환합니다. __index 메서드가 테이블이면, 반복하여 1、2、3;__index 메서드가 함수라면, 그 함수의 반환 값을 반환합니다。
이 부분 내용은 저자 환자에서 가져옵니다: https://blog.csdn.net/xocoder/article/details/9028347
__newindex 메서드는 테이블 업데이트에 사용되며, __index는 테이블 접근에 사용됩니다.
테이블의 누락된 인덱스에 값을 할당하면, 해석자는 __newindex 메서드를 찾습니다: 존재하면 이 함수를 호출하여 할당 작업을 수행하지 않습니다.
다음 예제에서는 __newindex 메서드의 사용을 설명합니다:
mymetatable = {} mytable = setmetatable({key1 = "value1"} print(mytable.key1) mytable.newkey = "새 값"}2" print(mytable.newkey,mymetatable.newkey) mytable.key1 = "새 값1" print(mytable.key1,mymetatable.key1)
위 예제의 실행 결과는 다음과 같습니다:
value1 nil 새 값2 새 값1 nil
위 예제에서 테이블에 __newindex 원 방법이 설정되었으며, 새 인덱스 키(newkey)에 대입할 때(mytable.newkey = "새 값2),면 대응 원 방법을 호출하지 않고 대입이 수행됩니다. 그리고 이미 존재하는 인덱스 키(key1)이면 대응 원 방법 __newindex를 호출하지 않고 대입이 수행됩니다.
다음 예제에서 rawset 함수를 사용하여 테이블을 업데이트하는 방법을 보여줍니다:
mytable = setmetatable({key1 = "value1"}, { __newindex = function(mytable, key, value) rawset(mytable, key, "\""..value.."\"") end ) mytable.key1 = "new value" mytable.key2 = 4 print(mytable.key1,mytable.key2)
위 예제의 실행 결과는 다음과 같습니다:
new value "4"
다음 예제에서 두 테이블의 합 연산을 보여줍니다:
-- 표의 최대 값을 계산합니다, table.maxn을 Lua에서5.2이 버전에서는 더 이상 사용할 수 없습니다. -- 표의 최대 키 값을 계산하는 고유한 계산 함수 table_maxn을 정의합니다. 즉, 표의 요소 개수를 계산합니다 function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 두 테이블의 합 연산 mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) for i = 1, table_maxn(newtable) do table.insert(mytable, table_maxn(mytable)+1,newtable[i]) end return mytable end ) secondtable = {4,5,6} mytable = mytable + secondtable for k,v in ipairs(mytable) do print(k,v) end
위 예제의 실행 결과는 다음과 같습니다:
1 1 2 2 3 3 4 4 5 5 6 6
__add 키가 원 테이블에 포함되어 더하기 연산이 수행됩니다。 테이블에 대응하는 연산 목록은 다음과 같습니다:(주의:__은 두 개의 밑줄)
모드 | 설명 |
---|---|
__add | 대응 연산자 '".+'. |
__sub | 대응 연산자 '".-'. |
__mul | 대응 연산자 '".*'. |
__div | 대응 연산자 '"./'. |
__mod | 대응 연산자 '%'. |
__unm | 대응 연산자 '".-'. |
__concat | 대응 연산자 '..'. |
__eq | 대응 연산자 '=='. |
__lt | 대응 연산자 '<'. |
__le | 대응 연산자 '<='. |
__call 원 방법 Lua에서 값을 호출할 때 호출됩니다. 다음 예제에서 테이블 요소의 합을 계산하는 방법을 보여줍니다:
-- 표의 최대 값을 계산합니다, table.maxn을 Lua에서5.2이 버전에서는 더 이상 사용할 수 없습니다. -- 표의 최대 키 값을 계산하는 고유한 계산 함수 table_maxn을 정의합니다. 즉, 표의 요소 개수를 계산합니다 function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 메타 메서드 __call 정의 mytable = setmetatable({10}, { __call = function(mytable, newtable) sum = 0 for i = 1, table_maxn(mytable) do sum = sum + mytable[i] end for i = 1, table_maxn(newtable) do sum = sum + newtable[i] end return sum end ) newtable = {10,20,30} print(mytable(newtable))
위 예제의 실행 결과는 다음과 같습니다:
70
__tostring 메타 메서드는 표의 출력 행동을 수정하는 데 사용됩니다. 다음 예제에서는 표의 출력 내용을 정의했습니다:
mytable = setmetatable({ 10, 20, 30 }, { __tostring = function(mytable) sum = 0 for k, v in pairs(mytable) do sum = sum + v end return "표의 모든 요소의 합은" .. sum end ) print(mytable)
위 예제의 실행 결과는 다음과 같습니다:
표의 모든 요소의 합은 60
이 글을 통해 우리는 메타테이블이 코드 기능을 크게 간소화할 수 있다는 것을 알 수 있습니다. 따라서 Lua의 메타테이블을 이해하면 더 간단하고 우수한 Lua 코드를 작성할 수 있습니다.