Menu
Coddy logo textTech

위임

Coddy Lua 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 70개 중 50번째.

객체 내부에 다른 객체를 저장하는 것은 첫 번째 단계일 뿐입니다. 컴포지션(composition)의 진정한 힘은 위임(delegation)에서 나옵니다. 이는 외부 객체가 메서드 호출을 내부 구성 요소로 전달할 때 발생합니다.

자동차를 시동 거는 것에 대해 생각해 보세요. 보닛 아래로 손을 뻗어 엔진을 수동으로 돌리지 않습니다. 대신, 키를 돌리면 자동차가 내부적으로 나머지를 처리합니다.

코드에서 이는 Car 클래스가 실제 작업을 엔진에 위임하는 간단한 :start() 메서드를 제공함을 의미합니다:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- 내부 객체에 위임
end

자동차는 엔진이 어떻게 작동하는지 알 필요가 없습니다—그저 엔진에게 할 일을 하라고 지시할 뿐입니다. 이는 책임을 분리된 상태로 유지합니다. Engine 클래스는 엔진 로직을 처리하고, Car는 각 부품들을 조율합니다:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- 출력:
-- 키를 돌리는 중...
-- Engine running at 250 HP

위임(Delegation)은 클래스 사용자에게 깔끔한 인터페이스를 제공합니다. 사용자는 내부 부품이 아니라 자동차와 상호작용합니다. 나중에 다른 엔진 구현으로 교체하더라도 자동차의 공개 인터페이스는 동일하게 유지되며, 내부의 위임 방식만 변경됩니다.

challenge icon

챌린지

쉬움

위임(delegation)을 보여주는 음악 플레이어 시스템을 만들어 봅시다! Speaker 컴포넌트와 이를 포함하는 MusicPlayer를 만들게 됩니다. 플레이어는 사운드 출력을 직접 처리하지 않고, 대신 그 책임을 내부 스피커에 위임합니다.

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

  • Speaker.lua: 볼륨 레벨을 저장하는 생성자 :new(volume)를 가진 Speaker 클래스를 만듭니다. Playing "{trackName}" at volume {volume}를 출력하는 :playSound(trackName) 메서드를 포함하세요.
  • MusicPlayer.lua: 브랜드 이름과 Speaker 객체를 인자로 받는 생성자 :new(brand, speaker)를 가진 MusicPlayer 클래스를 만듭니다. 플레이어는 내부에 스피커를 저장합니다. 다음 메서드들을 포함하세요:
    • :play(trackName){brand} player starting...을 출력한 다음, 스피커의 :playSound() 메서드에 위임합니다.
    • :stop(){brand} player stopped를 출력합니다.
  • main.lua: 모든 것을 하나로 합칩니다! 스피커 볼륨, 플레이어 브랜드, 트랙 이름에 대한 입력을 읽습니다. 먼저 Speaker를 생성한 다음, 이를 MusicPlayer 생성자에 전달합니다. 트랙 이름과 함께 플레이어의 :play() 메서드를 호출한 다음, :stop()을 호출합니다.

세 가지 입력을 받게 됩니다:

  1. 스피커 볼륨 (숫자)
  2. 음악 플레이어 브랜드 (문자열)
  3. 재생할 트랙 이름 (문자열)

출력은 플레이어가 스피커와 협력하는 모습을 보여주어야 합니다:

{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stopped

예를 들어, 입력이 75, SoundMax, Summer Vibes라면 출력은 다음과 같아야 합니다:

SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stopped

MusicPlayer가 소리를 내는 방법을 직접 알지 못하고, 단순히 스피커에게 그 부분을 처리하도록 지시하는 방식에 주목하세요. 이것이 바로 위임의 실제 사례입니다. 외부 객체는 깔끔한 인터페이스를 제공하고, 내부 컴포넌트가 전문적인 작업을 수행합니다!

치트 시트

위임(Delegation)을 사용하면 외부 객체가 메서드 호출을 내부 구성 요소로 전달할 수 있으므로, 책임을 분리하고 깔끔한 인터페이스를 만들 수 있습니다.

외부 객체는 내부 객체에 작업을 위임하는 간단한 메서드를 제공합니다:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- 내부 객체로 위임
end

내부 객체는 자체적인 전문 로직을 처리합니다:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Output:
-- Turning the key...
-- Engine running at 250 HP

위임의 장점:

  • 외부 클래스는 내부 객체가 어떻게 작동하는지 알 필요가 없습니다.
  • 사용자는 깔끔한 공개 인터페이스와 상호작용합니다.
  • 공개 인터페이스를 변경하지 않고도 내부 구현을 교체할 수 있습니다.

직접 해보기

-- main.lua
-- 모든 것을 하나로 합칩니다!

local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')

-- 입력 읽기
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()

-- TODO: 주어진 볼륨으로 Speaker 생성

-- TODO: 브랜드와 스피커로 MusicPlayer 생성

-- TODO: 트랙 이름으로 플레이어의 play 메서드 호출

-- TODO: 플레이어의 stop 메서드 호출
quiz icon실력 점검

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

Object Oriented Programming의 모든 레슨