Menu
Coddy logo textTech

Trait 충돌 해결

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

두 트레이트가 같은 이름의 method를 정의하면 PHP는 치명적인 오류를 발생시킵니다. insteadofas 연산자를 사용하여 이 conflict를 처리하는 방법을 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 occurred

insteadof 연산자는 충돌이 발생했을 때 사용할 트레이트의 method를 선택합니다. 이 예제에서는 FileLogger::log가 우선되어 default log() method가 됩니다. as 연산자는 alias를 생성하여 다른 트레이트의 method에 다른 이름으로 접근할 수 있게 합니다.

as를 사용하여 메서드의 가시성을 변경할 수도 있습니다:

<?php
trait Greeting {
    public function sayHello(): void {
        echo "Hello!";
    }
}

class Person {
    use Greeting {
        sayHello as private;
    }
}

이렇게 하면 트레이트에서는 public이더라도 sayHello()Person 클래스 내에서 private이 됩니다. 충돌 해결을 사용하면 트레이트 메서드가 클래스에 통합되는 방식을 세밀하게 제어할 수 있습니다.

challenge icon

챌린지

쉬움

서로 다른 채널이 메시지를 보낼 수 있지만, 여러 트레이트가 동일한 method 이름을 제공할 때 충돌을 resolve해야 하는 notification 시스템을 만들어 봅시다.

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

  • EmailNotifier.php: EmailNotifier이라는 트레이트를 Create하고, "Email: [message]"를 반환하는 notify(string $message) method를 만듭니다.
  • SmsNotifier.php: SmsNotifier라는 트레이트를 Create하고, "SMS: [message]"를 반환하는 notify(string $message) method를 만듭니다.
  • AlertService.php: both 트레이트를 사용하는 AlertService class를 Create합니다. 두 트레이트 모두 notify() method를 have 있으므로 이 conflict를 resolve해야 합니다:
    • EmailNotifier::notify를 기본 notify() method로 사용합니다.
    • SmsNotifier::notify method에 대해 notifyBySms alias를 Create합니다.
    또한 both notification method를 call하고, 이를 별도의 줄에 combined하여 반환하는 notifyAll(string $message) method를 추가합니다.
  • main.php: 필요한 모든 파일을 포함하고 AlertService instance를 Create합니다. 하나의 input, 즉 메시지 string을 받습니다. 다음 세 줄을 Print합니다:
    • 메시지와 함께 notify()를 calling한 결과
    • 메시지와 함께 notifyBySms()를 calling한 결과
    • 메시지와 함께 notifyAll()을 calling한 결과

이 예제는 이름 충돌이 발생했을 때 insteadof가 어떤 트레이트의 method가 우선할지 resolve하는 방법과, as를 사용하면 다른 트레이트의 method에 다른 이름으로 계속 액세스할 수 있는 방법을 보여 줍니다.

직접 해보기

<?php
require_once 'AlertService.php';

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

// TODO: AlertService 인스턴스 생성

// TODO: message와 함께 notify()를 호출한 결과 출력

// TODO: message와 함께 notifyBySms()를 호출한 결과 출력

// TODO: message와 함께 notifyAll()를 호출한 결과 출력
?>
quiz icon실력 점검

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

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

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