믹스인 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)이 패턴은 두 가지 장점을 모두 제공합니다. 공유된 정체성을 위한 명확한 클래스 계층 구조와, 필요한 곳에 혼합할 수 있는 유연한 기능을 함께 제공합니다.
챌린지
쉬움상속과 믹스인 중 언제 무엇을 사용해야 하는지 보여 주는 작은 생태계를 만들어 봅시다! Animal 기본 클래스를 만들고, 이를 상속하는 Bird와 Swimmable 믹스인을 만들 것입니다. 모든 새가 동물이기는 하지만 모든 새가 수영할 수 있는 것은 아니기 때문입니다.
코드를 네 개의 파일로 구성합니다:
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()을 호출합니다.
두 개의 입력을 받습니다:
- 새의 이름(문자열)
- 새의 수영 가능 여부:
yes또는no
새가 수영할 수 있다면 출력은 다음과 같아야 합니다:
{name} is eating
{name} chirps!
{name} is swimming새가 수영할 수 없다면 출력은 다음과 같아야 합니다:
{name} is eating
{name} chirps!예를 들어 입력이 Duck과 yes라면 출력은 다음과 같아야 합니다:
Duck is eating
Duck chirps!
Duck is swimming입력이 Sparrow와 no라면 출력은 다음과 같아야 합니다:
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() 호출
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍 (Object Oriented Programming)의 모든 레슨
직접 연습해 보세요: 온라인 Lua 컴파일러