인스턴스 변수
Coddy Lua 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 70개 중 12번째.
객체가 내부 데이터를 관리하는 방법에 초점을 맞춘 새로운 장에 오신 것을 환영합니다. 여러분은 클래스와 인스턴스를 생성하는 방법을 배웠습니다. 이제 각 인스턴스가 고유한 상태를 어떻게 저장하고 관리하는지 살펴볼 차례입니다.
인스턴스 변수는 단일 객체에만 전적으로 속하는 필드입니다. 메서드나 생성자 내부에서 self.something에 값을 할당하면, 해당 데이터는 오직 그 특정 인스턴스에만 존재합니다. 동일한 클래스의 다른 객체들은 각자 별도의 복사본을 가집니다.
이것은 테이블과 같은 복잡한 데이터를 저장할 때 특히 중요해집니다. 각 캐릭터가 서로 다른 아이템을 소지하는 인벤토리 시스템을 생각해 보세요:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- 각 인스턴스는 자신만의 빈 테이블을 가집니다
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
end핵심이 되는 줄은 instance.items = {}입니다. 생성자 내부에서 새로운 빈 테이블을 생성함으로써, 모든 인벤토리 객체는 자신만의 고유한 리스트를 갖게 됩니다. 만약 대신 items를 클래스 테이블 자체에 정의했다면, 모든 인스턴스가 실수로 동일한 테이블을 공유하게 될 것입니다. 즉, 한 캐릭터에게 검을 추가하면 모든 캐릭터가 검을 갖게 됩니다!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- 출력: 1
print(#bag2.items) -- 출력: 1각 인벤토리는 자체적인 컬렉션을 유지합니다. 이 패턴은 인스턴스가 독립적으로 변경되는 데이터(리스트, 카운터 또는 해당 객체에 고유한 가변 상태)를 추적해야 할 때마다 적용됩니다.
챌린지
쉬움각 장바구니가 고유한 제품 목록을 유지하는 ShoppingCart 시스템을 만들어 보겠습니다. 이를 통해 인스턴스 변수가 객체 간에 데이터를 어떻게 격리하는지 확인할 수 있습니다. 한 장바구니에 항목을 추가해도 다른 장바구니에는 영향을 주지 않습니다!
코드는 다음 두 개의 파일로 구성됩니다:
ShoppingCart.lua: 각 인스턴스가 고유한products테이블을 갖는ShoppingCart클래스를 정의합니다. 다음을 포함해야 합니다:- 각 장바구니에 대해 빈 제품 목록을 초기화하는
:new()생성자 - 해당 장바구니의 목록에 제품을 추가하는
:addProduct(productName)메서드 - 각 제품을 별도의 줄에 출력하는
:listProducts()메서드
- 각 장바구니에 대해 빈 제품 목록을 초기화하는
main.lua: ShoppingCart 모듈을 불러오고(require) 두 개의 별도 장바구니를 생성합니다. 각 장바구니가 독립적인 목록을 유지하는지 증명하기 위해 서로 다른 제품을 추가합니다.
네 개의 입력을 받게 됩니다:
- 장바구니 A에 추가할 첫 번째 제품
- 장바구니 A에 추가할 두 번째 제품
- 장바구니 B에 추가할 첫 번째 제품
- 장바구니 B에 추가할 두 번째 제품
메인 파일에서 다음을 수행하세요:
- 두 개의 장바구니
cartA와cartB를 생성합니다. - 처음 두 제품을
cartA에 추가합니다. - 마지막 두 제품을
cartB에 추가합니다. Cart A:를 출력한 다음 장바구니 A의 제품들을 나열합니다.Cart B:를 출력한 다음 장바구니 B의 제품들을 나열합니다.
예를 들어, 입력이 Apple, Bread, Milk, Eggs인 경우 출력은 다음과 같아야 합니다:
Cart A:
Apple
Bread
Cart B:
Milk
Eggs기억하세요: 핵심은 생성자 내부에서 products를 새로운 빈 테이블로 초기화하는 것입니다. 이렇게 하면 모든 장바구니가 하나의 테이블을 공유하는 대신, 각 장바구니 인스턴스가 자신만의 별도 목록을 갖게 됩니다.
치트 시트
인스턴스 변수는 단일 객체에만 독점적으로 속하는 필드입니다. 메서드나 생성자 내부에서 self.something에 값을 할당하면, 해당 데이터는 그 특정 인스턴스에만 존재하게 됩니다.
인스턴스 변수를 생성하려면, 각 인스턴스마다 새로운 테이블을 사용하여 생성자 내부에서 초기화하십시오:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- 각 인스턴스는 자신만의 빈 테이블을 가집니다.
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
end핵심은 instance.items = {}입니다. 생성자 내부에서 새로운 빈 테이블을 생성함으로써 모든 객체가 자신만의 고유한 데이터를 갖도록 보장합니다. 만약 클래스 테이블 자체에 items를 정의했다면, 모든 인스턴스가 동일한 테이블을 공유하게 되었을 것입니다.
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- 출력: 1
print(#bag2.items) -- 출력: 1각 인스턴스는 자신의 컬렉션을 독립적으로 유지합니다. 이 패턴은 리스트, 카운터 또는 인스턴스마다 변경되는 기타 데이터와 같이 객체에 고유한 모든 가변 상태(mutable state)에 적용됩니다.
직접 해보기
-- ShoppingCart 모듈을 불러옵니다
local ShoppingCart = require('ShoppingCart')
-- 입력을 읽습니다
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: 두 개의 쇼핑 카트 cartA와 cartB를 생성하세요
-- TODO: cartA에 product1과 product2를 추가하세요
-- TODO: cartB에 product3과 product4를 추가하세요
-- TODO: "Cart A:"를 출력한 후 cartA의 상품 목록을 나열하세요
-- TODO: "Cart B:"를 출력한 후 cartB의 상품 목록을 나열하세요
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.