본문 바로가기
이미지맥스 그리고 루아(lua)/루아(lua)

[lua] 클래스 Class (객체지향 프로그래밍)

by 위치결정 2022. 3. 26.
반응형

루아에서 테이블은 기능이 아주 강력합니다.

간단하게는 리스트에 데이터 배열을 만들수도 있고, 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

 

Programming in Lua : 16.1

This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences. The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores. By buying the book, you also help to support the Lu

www.lua.org

 

반응형

댓글