Lua MetaTable & 객체지향(OOP)

고은찬·2021년 6월 20일
0

Roblox / Lua

목록 보기
2/2

참고한 사이트
1. https://developer.roblox.com/en-us/articles/Metatables (공홈-metatables)
2. https://ospace.tistory.com/246 (Lua에서 객체지향적 코딩하기)
3. https://toughrogrammer.tistory.com/111 (Lua OOP Tutorial)
4. https://ospace.tistory.com/98 (메타테이블 정리글)
5. https://www.youtube.com/watch?v=2TC-bx0YfGk&list=PLXSd5YZgxaXSjGBMAn5FqdtZIG-3Gsp4z&index=1 (MetaTable & OOP Programming)
6. https://studymake.tistory.com/36 (메타테이블의 __index)

메타테이블을 왜 쓰는가?

루아에서 테이블은 유일한 자료형이다.
대부분의 작업이 이 테이블을 통해 이루어지지만, 한계가 존재한다.
1. 테이블 간의 비교와 연산이 불가능하다.

Result = table1 + table2
print(Result) -- nil

메타테이블을 사용함으로서 테이블의 제한점들을 극복 하고, 이를 활용해 Class개념이 없는 Lua에서 객체지향프로그래밍을 어느 정도 구현할 수 있다.
테이블간의 연산이 가능하고 필요시 다른 작업으로 치환해 사용할 수 있다.

메타테이블 설명

테이블에 메타테이블을 붙일 수 있다.
이 메타테이블에 미리 정해진 필드가 채워져 있다면, 이것에 의해서 메타테이블이 붙어있는 원래 테이블의 동작(특성)을 바꿀 수 있다.
=> 메타테이블에 미리 정의되어있는 함수들로 함수를 재정의 할 수 있다. (오버라이딩 느낌)

어떤 테이블에 메타테이블을 붙힐때 setmetatable() 함수를 사용한다.


local originTable = {}
local newMetaTable = {}

--[[메타테이블을 테이블에 붙히는 코드]]
--아래 2개의 코드는 동일하게 동작한다.

-- originTable 테이블에 newMetaTable을 첨가
setmetatable(originTable , newMetaTable)

-- 빈 테이블에 메타테이블인 newMetaTable 을 첨가한 것을 originTable에 반환
originTable = {setmetatable({} , newMetaTable)}



--[[메타테이블 확인 함수]]
-- 메타테이블이 설정되어 있다면 메모리에 할당된 위치값 반환
-- 메타테이블이 설정되어 있지 않다면 nil 반환
getmetatable(originTable)






메타메소드

메타 메소드는 메타 테이블 내부에 저장되는 함수이다.
테이블을 호출하거나, 테이블을 추가하거나, 테이블을 분할하는 작업 등을 수행한다.

메타테이블에는 정해진 문자열 키값을 갖는 테이블을 필드로 가져야 되는데 이 미리 정해진 문자열 키값들의 리스트이다.

<공식홈페이지 캡쳐>

<간략하게 정리본>

-- 간략하게 정리본

+ 연산 - __add

- 연산 - __sub

* 연산 - __mul

/ 연산 - __div

^ 연산 - __pow

- (음수 연산자) - __unm

< 연산 - __lt

<= 연산 - __le

.. 연산 - __concat

테이블에 인덱스 값을 얻을 때 - __index

테이블에 유효한 인덱스 값을 얻을 때 - __gettable

테이블에 새로운 인덱스 값을 만들려고 할 때 - __newindex

테이블에 인덱스에 새로운 값을 저장하려고 할 때 - __settable

함수가 호출 될 때 - __call

가비지 컬렉션이 호출 될 때 - __gc



__index

예시로 __index를 설명하자면
만약 테이블 originTable 의 키값으로 요소들을 접근하려고 할 때

originTable.keyOne
originTable[1]
originTable["FunctionA"] 

이런 방법들을 사용할 것이다.
키값이 originTable 안에 없을 때는 nil을 반환할 것이다.

하지만 originTable 에 메타테이블이 연결되어 있다면 그 연결된 메타테이블의 __index 테이블에 등록된 필드를 추가로 검사한다.

예를 들어

local originTable = { x = 10 }
print(originTable.y)	--"y"라는 key값이 없으므로 nil 출력

local metatable = { 
	__index = { y = 20 }
}

setmetatable(originTable,metatable)
print(originTable.y) 	--metatable 안에 있는 y 값인 20이 출력

__index 는 originTable(메타테이블이 연결된 경우) 에 없는 키값을 참조할 경우에 실행되어 연결된 메타테이블에서 키값을 검색한다.

메타테이블의 __index 내부에는 함수도 정의 할 수 있다.

local mathIndex = {}
function mathindex:sum() 
	return self.x + self.y
end

local tableA = { 
	x = 10,
    	y = 20
}

setmetatable(tableA, {__index = mathIndex})
print(tableA:sum()) 	--30

local tableB = setmetatable( {x=30, y=40}, {__index = mathIndex} )
print(tableB:sum())	--70



메타테이블을 클래스처럼 활용하는 방법

profile
연애하는 개발자

1개의 댓글