Menu
Coddy logo textTech

메서드 오버라이딩 다시 살펴보기

Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 91개 중 33번째.

상속 챕터에서 메서드 오버라이딩에 대해 이미 배웠습니다. 이제 이것이 객체 지향 프로그래밍의 가장 강력한 개념 중 하나인 다형성(polymorphism)과 어떻게 연결되는지 살펴보겠습니다.

다형성(Polymorphism)은 "여러 가지 형태"를 의미합니다. 자식 클래스에서 메서드를 오버라이드(override)할 때, 동일한 이름을 유지하면서 해당 메서드에 다른 형태를 부여하게 됩니다. 마법 같은 일은 부모 타입을 통해 객체를 다룰 때 일어납니다:

<?php
class Animal {
    public function speak() {
        return "Some sound";
    }
}

class Dog extends Animal {
    public function speak() {
        return "Woof!";
    }
}

class Cat extends Animal {
    public function speak() {
        return "Meow!";
    }
}

function makeAnimalSpeak(Animal $animal) {
    return $animal->speak();
}

echo makeAnimalSpeak(new Dog()) . "\n";
echo makeAnimalSpeak(new Cat());

출력:

Woof!
Meow!

makeAnimalSpeak() 함수는 어떤 Animal이든 받아들입니다. 이 함수는 Dog를 받는지 Cat을 받는지 알지 못하며 신경 쓰지 않습니다. PHP는 런타임 시 실제 객체 유형에 따라 올바른 오버라이드된 메서드를 자동으로 호출합니다.

이것은 다형성이 실제로 작동하는 모습입니다.

이 접근 방식을 사용하면 구체적인 타입을 알지 못해도 일련의 관련 객체들과 함께 작동하는 유연한 코드를 작성할 수 있습니다. 나중에 새로운 동물 클래스를 추가하더라도 함수는 자동으로 해당 클래스들과 함께 작동합니다.

핵심 포인트: 메서드 오버라이딩은 서로 다른 클래스가 동일한 메서드 호출에 대해 다르게 응답할 수 있도록 함으로써 다형성을 가능하게 하며, 이는 런타임 시 실제 객체 유형에 의해 결정됩니다.

challenge icon

챌린지

쉬움

메서드 오버라이딩을 통해 다형성을 보여주는 악기 시스템을 구축해 보겠습니다. 기본 Instrument 클래스와 각각 고유한 소리를 내는 두 개의 자식 클래스를 만든 다음, 단일 함수를 사용하여 모든 악기를 다형성 있게 연주해 볼 것입니다.

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

  • Instrument.php — 생성자를 통해 설정되는 보호된(protected) $name 속성을 가진 Instrument 클래스를 만듭니다. "[name] makes a sound"를 반환하는 play() 메서드를 추가합니다. 이것은 자식 클래스가 오버라이드할 기본 동작 역할을 합니다.
  • Guitar.phpInstrument를 상속받는 Guitar 클래스를 만듭니다. 부모 파일을 포함(include)하세요. 생성자는 이름을 받아 부모 생성자에 전달합니다. play() 메서드를 오버라이드하여 "[name] strums a chord"를 반환하도록 합니다.
  • Drum.phpInstrument를 상속받는 Drum 클래스를 만듭니다. 부모 파일을 포함하세요. 생성자는 이름을 받아 부모 생성자에 전달합니다. play() 메서드를 오버라이드하여 "[name] beats a rhythm"을 반환하도록 합니다.
  • main.php — Guitar와 Drum 파일을 모두 포함합니다. Instrument 매개변수(타입 힌트 적용)를 받아 해당 객체의 play()를 호출한 결과를 반환하는 performWith라는 함수를 만듭니다. 이 함수는 다형성을 보여줍니다. 부모 클래스 타입 힌트를 통해 어떤 악기 유형과도 작동합니다.

기타의 이름과 드럼의 이름이라는 두 개의 입력을 받게 됩니다. 이 이름들로 GuitarDrum 객체를 생성하세요. 각각을 performWith() 함수에 전달하고 결과를 출력합니다. 기타를 먼저 출력하고 그 다음에 드럼을 출력하며, 각각 별도의 줄에 출력합니다.

performWith()가 모든 Instrument를 수용하지만, PHP가 런타임 시 실제 객체 유형에 따라 올바르게 오버라이드된 play() 메서드를 자동으로 호출하는 방식에 주목하세요. 이것이 바로 실행 중인 다형성입니다!

치트 시트

다형성(Polymorphism)은 "여러 형태"를 의미하며, 서로 다른 클래스의 객체들이 각각의 고유한 동작을 유지하면서도 부모 타입을 통해 다뤄질 수 있도록 합니다.

자식 클래스에서 메서드를 오버라이드(재정의)하면, PHP는 런타임 시 실제 객체 타입에 따라 자동으로 올바른 버전을 호출합니다:

<?php
class Animal {
    public function speak() {
        return "Some sound";
    }
}

class Dog extends Animal {
    public function speak() {
        return "Woof!";
    }
}

class Cat extends Animal {
    public function speak() {
        return "Meow!";
    }
}

function makeAnimalSpeak(Animal $animal) {
    return $animal->speak();
}

echo makeAnimalSpeak(new Dog()); // Woof!
echo makeAnimalSpeak(new Cat()); // Meow!

makeAnimalSpeak() 함수는 매개변수 타입 힌트를 통해 모든 Animal 타입을 허용합니다. 이 함수는 구체적인 클래스를 알 필요가 없습니다. PHP가 런타임에 실제 객체 타입을 기반으로 어떤 오버라이드된 메서드를 호출할지 결정하기 때문입니다.

이를 통해 구체적인 타입을 알지 못해도 연관된 객체 그룹과 함께 작동하는 유연한 코드를 작성할 수 있습니다. 나중에 새로운 자식 클래스가 추가되더라도 기존 함수들과 자동으로 연동됩니다.

직접 해보기

<?php
// 악기 파일 포함
require_once 'Guitar.php';
require_once 'Drum.php';

// 입력 읽기
$guitarName = trim(fgets(STDIN));
$drumName = trim(fgets(STDIN));

// TODO: 다음과 같은 performWith 함수를 생성하세요:
// - Instrument 매개변수를 받습니다 (타입 힌트 사용: Instrument $instrument)
// - 악기에서 play()를 호출한 결과를 반환합니다

// TODO: $guitarName으로 Guitar를 생성하고 $drumName으로 Drum을 생성하세요
// TODO: 각각을 performWith()에 전달하고 결과를 출력하세요 (기타 먼저, 그 다음 드럼)

?>
quiz icon실력 점검

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

객체 지향 프로그래밍의 모든 레슨