트레이트 충돌 해결
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 91개 중 53번째.
두 개의 트레이트(trait)가 동일한 이름의 메서드를 정의하면, PHP는 치명적 오류(fatal error)를 발생시킵니다. insteadof와 as 연산자를 사용하여 이 충돌을 처리하는 방법을 PHP에 명시적으로 알려주어야 합니다.
<?php
trait FileLogger {
public function log(string $message): void {
echo "File: $message";
}
}
trait DatabaseLogger {
public function log(string $message): void {
echo "DB: $message";
}
}
class Application {
use FileLogger, DatabaseLogger {
FileLogger::log insteadof DatabaseLogger;
DatabaseLogger::log as logToDatabase;
}
}
$app = new Application();
$app->log("Error occurred");
$app->logToDatabase("Error occurred");
출력:
File: Error occurred
DB: Error occurredinsteadof 연산자는 충돌이 발생했을 때 어떤 트레이트(trait)의 메서드를 사용할지 선택합니다. 이 예제에서는 FileLogger::log가 우선권을 가지며 기본 log() 메서드가 됩니다. as 연산자는 별칭(alias)을 생성하여, 다른 트레이트의 메서드를 다른 이름으로 접근할 수 있게 해줍니다.
또한 as를 사용하여 메서드의 가시성을 변경할 수 있습니다:
<?php
trait Greeting {
public function sayHello(): void {
echo "Hello!";
}
}
class Person {
use Greeting {
sayHello as private;
}
}
이것은 sayHello()가 trait에서는 public임에도 불구하고, Person 클래스 내에서 private이 되도록 만듭니다. 충돌 해결(Conflict resolution)을 통해 trait 메서드가 클래스에 통합되는 방식을 세밀하게 제어할 수 있습니다.
챌린지
쉬움여러 트레이트(trait)가 동일한 메서드 이름을 제공할 때 발생하는 충돌을 해결하면서, 다양한 채널을 통해 메시지를 보낼 수 있는 알림 시스템을 구축해 보겠습니다.
코드는 다음 네 개의 파일로 구성됩니다:
EmailNotifier.php—"Email: [message]"를 반환하는notify(string $message)메서드를 가진EmailNotifier트레이트를 생성합니다.SmsNotifier.php—"SMS: [message]"를 반환하는notify(string $message)메서드를 가진SmsNotifier트레이트를 생성합니다.AlertService.php— 두 트레이트를 모두 사용하는AlertService클래스를 생성합니다. 두 트레이트 모두notify()메서드를 가지고 있으므로, 다음과 같이 충돌을 해결해야 합니다:EmailNotifier::notify를 기본notify()메서드로 사용합니다.SmsNotifier::notify메서드에 대해notifyBySms라는 별칭(alias)을 생성합니다.
notifyAll(string $message)메서드를 추가합니다.main.php— 필요한 모든 파일을 포함하고AlertService인스턴스를 생성합니다. 하나의 입력값으로 메시지 문자열을 받습니다. 다음 세 줄을 출력합니다:- 메시지와 함께
notify()를 호출한 결과 - 메시지와 함께
notifyBySms()를 호출한 결과 - 메시지와 함께
notifyAll()을 호출한 결과
- 메시지와 함께
이 과정은 이름 충돌이 발생했을 때 insteadof를 사용하여 어떤 트레이트의 메서드를 우선할지 결정하고, as를 사용하여 다른 트레이트의 메서드를 다른 이름으로 계속 사용할 수 있는 방법을 보여줍니다.
치트 시트
여러 트레이트(trait)가 동일한 이름의 메서드를 정의할 때, PHP는 insteadof 및 as 연산자를 사용한 명시적인 충돌 해결을 요구합니다.
insteadof 연산자는 어떤 트레이트의 메서드를 기본으로 사용할지 선택합니다:
<?php
trait FileLogger {
public function log(string $message): void {
echo "File: $message";
}
}
trait DatabaseLogger {
public function log(string $message): void {
echo "DB: $message";
}
}
class Application {
use FileLogger, DatabaseLogger {
FileLogger::log insteadof DatabaseLogger;
DatabaseLogger::log as logToDatabase;
}
}
$app = new Application();
$app->log("Error occurred"); // File: Error occurred
$app->logToDatabase("Error occurred"); // DB: Error occurred
as 연산자는 트레이트 메서드에 대한 별칭(alias)을 생성하여, 다른 이름으로 접근할 수 있게 해줍니다.
또한 as를 사용하여 메서드의 가시성(visibility)을 변경할 수 있습니다:
<?php
trait Greeting {
public function sayHello(): void {
echo "Hello!";
}
}
class Person {
use Greeting {
sayHello as private;
}
}
직접 해보기
<?php
require_once 'AlertService.php';
// 입력 읽기
$message = trim(fgets(STDIN));
// TODO: AlertService 인스턴스 생성
// TODO: 메시지와 함께 notify()를 호출한 결과 출력
// TODO: 메시지와 함께 notifyBySms()를 호출한 결과 출력
// TODO: 메시지와 함께 notifyAll()을 호출한 결과 출력
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8매직 메서드
매직 메서드 소개__toString 및 __debugInfo__get, __set, __isset, __unset__call 및 __callStatic__clone 및 객체 복제__serialize 및 __unserialize요약 - 커스텀 컬렉션