__index를 이용한 연결
Coddy Lua 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 70개 중 7번째.
속성과 메서드가 있는 프로토타입 테이블이 있지만, 새로운 객체가 실제로 그것을 사용하도록 하려면 어떻게 해야 할까요? 그 답은 __index 메타메서드에 있습니다.
테이블에 존재하지 않는 키에 접근할 때, Lua는 보통 nil을 반환합니다. 하지만 테이블에 __index 필드가 있는 메타테이블(metatable)이 있다면, Lua는 대신 그곳을 확인합니다. __index가 프로토타입을 가리키도록 설정하면, 누락된 키들을 프로토타입에서 자동으로 찾게 됩니다:
local Dog = {
species = "Canis familiaris",
legs = 4
}
function Dog:bark()
print("Woof!")
end
-- 빈 인스턴스 생성
local myDog = {}
-- 프로토타입에 연결
setmetatable(myDog, { __index = Dog })
print(myDog.species) -- 출력: Canis familiaris
myDog:bark() -- 출력: Woof!myDog 테이블은 완전히 비어 있지만, myDog.species에 접근하는 것은 작동합니다. Lua가 myDog에서 species를 찾지 못하면, 메타테이블의 __index를 확인하고 Dog에서 그것을 찾습니다.
이것은 Lua에서 객체 지향 프로그래밍의 기초입니다. 인스턴스는 자신만의 고유한 데이터를 가질 수 있으며, 공유된 동작은 프로토타입에 존재합니다. 다음 레슨에서는 이 패턴을 깔끔한 생성자 함수로 감싸는 방법을 배우게 됩니다.
챌린지
쉬움이제 __index 메타메소드를 실제로 적용해 봅시다! 프로토타입을 만들고 인스턴스를 여기에 연결하여, 인스턴스가 직접 가지고 있지 않은 속성과 메소드에 접근할 수 있도록 할 것입니다.
코드는 두 개의 파일로 구성됩니다:
Robot.lua: 다음을 포함하는Robot프로토타입 테이블을 정의합니다:model필드를"RX-100"으로 설정batteryLevel필드를100으로 설정- 로봇의 현재 상태를 출력하는
:status()메소드
main.lua: Robot 모듈을 불러온(require) 후, 빈 인스턴스 테이블을 생성하고setmetatable과__index를 사용하여 Robot 프로토타입에 연결합니다. 이를 통해 빈 인스턴스가 프로토타입의 모든 요소에 접근할 수 있게 됩니다.
하나의 입력을 받게 됩니다: 로봇 인스턴스에 할당할 이름입니다.
인스턴스를 프로토타입에 연결한 후:
- 입력받은 이름을 인스턴스의
name필드에 할당합니다 (이 필드는 인스턴스 고유의 값이 됩니다). - 인스턴스에서
:status()메소드를 호출합니다.
:status() 메소드는 반드시 다음 형식으로 출력해야 합니다:
[name] ([model]) - Battery: [batteryLevel]%예를 들어, 입력값이 Sparky라면 출력은 다음과 같아야 합니다:
Sparky (RX-100) - Battery: 100%인스턴스가 자신만의 name을 가지고 있지만, __index 연결을 통해 프로토타입으로부터 model과 batteryLevel에 접근하는 방식에 주목하세요.
치트 시트
__index 메타메소드는 객체가 프로토타입 테이블로부터 속성과 메소드를 상속받을 수 있게 해줍니다.
테이블에 존재하지 않는 키에 접근할 때, Lua는 해당 테이블에 __index 필드가 있는 메타테이블이 있는지 확인합니다. 만약 있다면, Lua는 __index에 지정된 테이블에서 해당 키를 찾습니다.
인스턴스를 프로토타입에 연결하려면:
local Prototype = {
property = "value"
}
function Prototype:method()
print("Method called")
end
-- 인스턴스 생성
local instance = {}
-- __index를 사용하여 프로토타입에 연결
setmetatable(instance, { __index = Prototype })
-- 프로토타입 속성 및 메소드에 접근
print(instance.property) -- 출력: value
instance:method() -- 출력: Method called인스턴스 테이블은 비어 있을 수 있지만, 프로토타입의 모든 속성과 메소드에 접근할 수 있습니다. 또한 인스턴스는 프로토타입을 오버라이드하거나 확장하는 자신만의 고유한 속성을 가질 수 있습니다.
이 패턴은 Lua에서 객체 지향 프로그래밍의 기초가 되며, 인스턴스는 자신만의 고유한 데이터를 유지하면서 프로토타입의 동작을 공유합니다.
직접 해보기
-- 입력 읽기
local name = io.read()
-- Robot 모듈 불러오기
local Robot = require('Robot')
-- TODO: 빈 인스턴스 테이블 생성
-- TODO: __index와 함께 setmetatable을 사용하여 인스턴스를 Robot 프로토타입에 연결
-- TODO: 입력받은 이름을 인스턴스의 name 필드에 할당
-- TODO: 인스턴스에서 :status() 메서드 호출
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.