Menu
Coddy logo textTech

믹스인 vs 상속

Coddy Lua 여정의 객체 지향 프로그래밍 (Object Oriented Programming) 섹션에 포함된 레슨. 70개 중 53번째.

동작을 공유하는 두 가지 방법을 배웠습니다. 상속은 프로토타입 체인을 통해 "is-a" 관계를 만들고, 믹스인은 함수를 클래스에 직접 복사합니다. 하지만 각각의 접근 방식을 언제 사용해야 할까요?

객체가 근본적인 정체성을 공유할 때 상속을 사용하세요. Bird하나의 Animal입니다. Bird:eat()이나 :sleep()과 같은 핵심 동물 동작을 상속하는 것은 타당합니다. 이 관계는 영구적이며 객체가 근본적으로 무엇인지를 정의합니다.

객체의 핵심 정체성을 정의하지 않는 기능을 추가하려면 믹스인을 사용하세요.

모든 새가 날 수 있는 것은 아닙니다. 펭귄과 타조는 새이지만 날지 못합니다. 비행은 새의 본질을 규정하는 특성이 아니라 능력입니다. Flyable 믹스인을 사용하면 모든 새에게 비행을 강요하지 않고도 비행이 필요한 새에 비행 기능을 추가할 수 있습니다.

두 가지 접근 방식은 함께 사용할 때 훌륭하게 작동합니다:

-- Bird는 Animal을 상속합니다 (is-a 관계)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})

-- Flyable은 능력입니다 (mixin)
local Flyable = {}
function Flyable:fly()
    print(self.name .. " soars through the sky!")
end

-- 날 수 있는 새들에게만 mixin을 적용합니다
applyMixin(Bird, Flyable)

이 패턴은 두 가지 장점을 모두 제공합니다. 공유된 정체성을 위한 명확한 클래스 계층 구조와, 필요한 곳에 혼합할 수 있는 유연한 기능을 함께 제공합니다.

challenge icon

챌린지

쉬움

상속과 믹스인 중 언제 무엇을 사용해야 하는지 보여 주는 작은 생태계를 만들어 봅시다! Animal 기본 클래스를 만들고, 이를 상속하는 BirdSwimmable 믹스인을 만들 것입니다. 모든 새가 동물이기는 하지만 모든 새가 수영할 수 있는 것은 아니기 때문입니다.

코드를 네 개의 파일로 구성합니다:

  • Animal.lua: 이름을 저장하는 생성자 :new(name)가 있는 기본 Animal 클래스를 만듭니다. {name} is eating을 출력하는 :eat() 메서드를 포함합니다. 이는 모든 동물이 공유하는 핵심 정체성을 나타냅니다.
  • Swimmable.lua: {self.name} is swimming을 출력하는 :swim() 메서드가 있는 믹스인을 만듭니다. 이는 능력이며, 모든 생물이 수영할 수 있는 것은 아니므로 상속 체인의 일부가 되어서는 안 됩니다.
  • Bird.lua: Animal을 상속하는 Bird 클래스를 만듭니다. :new(name, canSwim) 생성자는 부모 생성자를 호출하고 이 새가 수영할 수 있는지 저장해야 합니다. Bird 클래스에 Swimmable 믹스인을 적용합니다. {name} chirps!를 출력하는 :chirp() 메서드를 포함합니다. 이는 새에 특화된 동작입니다.
  • main.lua: 여기에서 applyMixin 도우미 함수를 작성합니다. 새의 이름과 수영 가능 여부(yes 또는 no)를 입력으로 읽습니다. Bird 인스턴스를 만든 다음, 그 능력을 보여 줍니다. :eat()(Animal에서 상속됨)을 호출하고, :chirp()(Bird 자체의 메서드)를 호출한 뒤, 새가 수영할 수 있는 경우에만 :swim()을 호출합니다.

두 개의 입력을 받습니다:

  1. 새의 이름(문자열)
  2. 새의 수영 가능 여부: yes 또는 no

새가 수영할 수 있다면 출력은 다음과 같아야 합니다:

{name} is eating
{name} chirps!
{name} is swimming

새가 수영할 수 없다면 출력은 다음과 같아야 합니다:

{name} is eating
{name} chirps!

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

Duck is eating
Duck chirps!
Duck is swimming

입력이 Sparrowno라면 출력은 다음과 같아야 합니다:

Sparrow is eating
Sparrow chirps!

이 챌린지는 핵심적인 차이를 보여 줍니다. Bird는 Animal이지만(상속), 수영은 선택적인 능력입니다(믹스인). 믹스인은 클래스에 적용되지만, 실제로 이를 사용할지는 개별 새의 능력에 따라 main 로직에서 결정합니다!

직접 해보기

-- main.lua: 진입점 - 새를 생성하고 그 능력을 시연합니다

-- 클래스에 믹스인을 적용하는 헬퍼 함수
local function applyMixin(class, mixin)
    -- TODO: mixin의 모든 메서드를 class에 복사
    
end

-- Bird를 require하기 전에 Swimmable 믹스인을 Bird에 적용
-- Note: Bird.lua에서 또는 여기서 이를 처리해야 할 수 있습니다

local Bird = require('Bird')
local Swimmable = require('Swimmable')

-- Bird 클래스에 믹스인 적용
applyMixin(Bird, Swimmable)

-- 입력 읽기
local name = io.read()
local canSwimInput = io.read()

-- TODO: 입력("yes" 또는 "no")을 기반으로 새가 수영할 수 있는지 결정

-- TODO: 이름과 수영 능력으로 Bird 인스턴스 생성

-- TODO: eat() 호출 - Animal에서 상속됨

-- TODO: chirp() 호출 - Bird 자체의 메서드

-- TODO: 새가 수영할 수 있는 경우에만 swim() 호출
quiz icon실력 점검

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

객체 지향 프로그래밍 (Object Oriented Programming)의 모든 레슨

직접 연습해 보세요: 온라인 Lua 컴파일러