Menu
Coddy logo textTech

__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에서 객체 지향 프로그래밍의 기초입니다. 인스턴스는 자신만의 고유한 데이터를 가질 수 있으며, 공유된 동작은 프로토타입에 존재합니다. 다음 레슨에서는 이 패턴을 깔끔한 생성자 함수로 감싸는 방법을 배우게 됩니다.

challenge icon

챌린지

쉬움

이제 __index 메타메소드를 실제로 적용해 봅시다! 프로토타입을 만들고 인스턴스를 여기에 연결하여, 인스턴스가 직접 가지고 있지 않은 속성과 메소드에 접근할 수 있도록 할 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • Robot.lua: 다음을 포함하는 Robot 프로토타입 테이블을 정의합니다:
    • model 필드를 "RX-100"으로 설정
    • batteryLevel 필드를 100으로 설정
    • 로봇의 현재 상태를 출력하는 :status() 메소드
    파일의 마지막에 테이블을 반환합니다.
  • main.lua: Robot 모듈을 불러온(require) 후, 빈 인스턴스 테이블을 생성하고 setmetatable__index를 사용하여 Robot 프로토타입에 연결합니다. 이를 통해 빈 인스턴스가 프로토타입의 모든 요소에 접근할 수 있게 됩니다.

하나의 입력을 받게 됩니다: 로봇 인스턴스에 할당할 이름입니다.

인스턴스를 프로토타입에 연결한 후:

  1. 입력받은 이름을 인스턴스의 name 필드에 할당합니다 (이 필드는 인스턴스 고유의 값이 됩니다).
  2. 인스턴스에서 :status() 메소드를 호출합니다.

:status() 메소드는 반드시 다음 형식으로 출력해야 합니다:

[name] ([model]) - Battery: [batteryLevel]%

예를 들어, 입력값이 Sparky라면 출력은 다음과 같아야 합니다:

Sparky (RX-100) - Battery: 100%

인스턴스가 자신만의 name을 가지고 있지만, __index 연결을 통해 프로토타입으로부터 modelbatteryLevel에 접근하는 방식에 주목하세요.

치트 시트

__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() 메서드 호출
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Object Oriented Programming의 모든 레슨