루아에서 테이블은 기능이 아주 강력합니다.
간단하게는 리스트에 데이터 배열을 만들수도 있고, key를 지정하여 딕셔너리형으로 데이터를 관리할수도 있으며, 함수를 정의할수도있습니다.
그리고 루아에서도 self 를 자기 자신을 지정할수있습니다.
테이블내에서 함수를 정의할때 . 이 아닌 : 로 선언하고, 함수 호출도 : 을 사용하면 self로 자기 자신을 매개변수로 받을수 있게 됩니다.
또 테이블의 행동을 정의할수 있는 metatable을 정의하면 원하는 연산동작을 지정할수 있게 됩니다.
이를 활용하면 일종의 객체지향 클래스를 루아에서도 구현할수 있습니다.
1. 부모 클래스
-- 부모 클래스 선언
Person = {}
function Person:new(name, age)
local instance = setmetatable({}, self) -- 인스턴스 instance에 Person 상속
self.__index = self
instance.name = name or 'chul-su'
instance.age = age or 20
return instance
end
function Person:hello()
print(string.format('Hello, My name is %s. I am %d years old', self.name, self.age))
end
a = Person:new()
a:hello()
-- > Hello, My name is chul-su. I am 20 years old
b = Person:new('min-ho', 25)
b:hello()
-- > Hello, My name is min-ho. I am 25 years old
Person 이라는 빈테이블을 만들고 이를 클래스화 하기위해 내부에 인스턴스 테이블을 생성후 메타테이블을 self 로 지정합니다. 그리고 __index 도 self 로 정의합니다.
a 변수에 Person:new() 함수를 호출하여 Person 객체를 생성합니다.
a는 name과 age를 가지고있습니다. 객체 생성시 아무값도 지정하지않았으니 기본값인 'chul-su'와 20이 저장되었을것입니다.
a:hello() 함수를 호출하면 a에는 없는 hello() 함수가 __index에 지정된 자기자신 Person을 참조하여 hello() 함수를 불러옵니다. 이때 hello() 함수에서 정의된 self는 a 입니다.
b 변수에는 Person:new('min-ho', 25) 를 호출하여 다른 이름과 나이를 가진 Person 객체를 생성하여봅니다.
b는 name에는 'min-ho' 그리고 age는 25가 저장되어있습니다.
마찮가지로 b:hello() 함수를 호출하면 b에는 없는 hello() 함수를 __index에 지정되어있는 자기자신 person을 참조하여 불러올 것입니다.
이때 self는 b이므로 name과 age는 min-ho, 25로 실행됩니다.
2. 자식 클래스 상속
-- 자식 클래스 선언, 상속
Child = {}
setmetatable(Child, Person) -- Child 클래스(자식)를 Person 클래스(부모) 상속
function Child:new(name, age)
local instance = setmetatable(Person:new(name, age), self)
self.__index = self
instance.schoolgrade = "A"
return instance
end
function Child:grade()
print(string.format('My grade : %s', self.schoolgrade))
end
c = Child:new('yong-ho', 14)
c:hello()
-- > Hello, My name is yong-ho. I am 14 years old
c:grade()
-- > My grade : A
클래스의 큰 특징중 하나는 부모 클래스와 자식 클래스 간의 상속 입니다.
이를 구현하기 위해 Child 테이블을 새로 만들고 Child 의 메타테이블을 Person 으로 설정합니다.
setmetatable(child, Person) 으로 자식클래스(Child)를 부모클래스(Person)에 상속할수있습니다.
그 이후는 위에서 했던것과 같이 Child 클래스를 new() 함수부터 정의합니다.
c변수에 Child:new('yong-ho', 14) 를 호출하여 Child의 새로운 객체를 생성합니다.
c의 name에는 'yong-ho' , age에는 14, grade에는 A 가 저장되었습니다.
똑같이 c:hello() 함수를 호출하면 c에는 없는 hello() 함수를 Child를 __index에 지정된 자기자신 Child을 참조하여 불러와야하지만 Child에도 hello()함수는 없습니다. 대신 Child은 메타테이블로 Person이 지정되어있습니다. 그러므로 Person에서 hello() 함수를 호출할 있습니다. 그래서 이를 참조하여 hello() 함수가 실행됩니다.
c:grade() 함수를 호출하면 __index에 지정된 자기자신을 참조하여 실행될것입니다.
이런식으로 __index를 먼저 참조하고 실행할수 없다면 metatable을 참조하여 동작하는 클래스의 상속 개념을 루아에서 구현할 수 있습니다.
그런데 왜 머리가 깨질것같죠.
참조문헌 : https://www.lua.org/pil/16.1.html
'이미지맥스 그리고 루아(lua) > 루아(lua)' 카테고리의 다른 글
[lua] 루아에서 윈도우 앱을 실행하는 방법 os.execute() (8) | 2021.09.20 |
---|---|
[lua] 함수 정의시 인수의 기본값 지정하는 방법 (869) | 2021.08.03 |
[lua] 랜덤 시간 예약 설정 함수 setTime() (4) | 2021.07.12 |
[lua] 시간 설정 및 경과 확인 함수 getClock() setClock() (4) | 2021.05.12 |
[lua] 루아에서 sleep() 함수를 구현하기 (2) | 2021.05.10 |
댓글