PHP OOP에서 트레이트 메서드 충돌 해결
하나의 클래스가 여러 트레이트를 사용할 수 있기 때문에, 두 트레이트가 동일한 이름의 메서드를 가질 때 문제가 발생할 수 있습니다.
이 경우 PHP는 치명적인 오류를 발생시킵니다. 상황을 해결하려면 명시적으로 이름 충돌을 해결해야 합니다. 어떻게 하는지 실제로 살펴보겠습니다.
동일한 method 메서드를 가진 두 개의 트레이트가 있다고 가정해 보겠습니다:
<?php
trait Trait1
{
private function method()
{
return 1;
}
}
trait Trait2
{
private function method()
{
return 2;
}
}
?>
두 트레이트를 모두 사용하는 Test 클래스도 있다고 가정해 보겠습니다.
단순히 두 트레이트를 우리 클래스에 연결하면,
트레이트에 중복 메서드가 있기 때문에 PHP가 오류를 발생시킵니다:
<?php
// 이 코드는 오류를 발생시킵니다!
class Test
{
use Trait1, Trait2; // 트레이트 연결
}
?>
우리 트레이트의 이름 충돌을 해결해 보겠습니다.
이를 위해 특별한 연산자 insteadof가 존재합니다.
이 연산자를 사용하여 트레이트 Trait2의 동일한 메서드 대신
트레이트 Trait1의 method 메서드를 사용하겠습니다:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
}
new Test;
?>
보시다시피 구문은 다음과 같습니다: 먼저 트레이트 이름,
그 다음 콜론 두 개, 그 다음 메서드 이름,
그 다음 우리의 연산자 insteadof, 그리고 두 번째 트레이트의 이름입니다.
확인해 봅시다:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
}
public function __construct()
{
echo $this->method(); // 첫 번째 트레이트의 메서드이므로 1을 출력합니다
}
}
new Test;
?>
따라서, 우리 클래스에서 method 메서드가 사용되면
첫 번째 트레이트에서 가져와야 한다고 지정했습니다.
반대로 두 번째 트레이트의 메서드를 가져올 수도 있습니다:
<?php
class Test
{
use Trait1, Trait2 {
Trait2::method insteadof Trait1;
}
public function __construct()
{
echo $this->method(); // 두 번째 트레이트의 메서드이므로 2를 출력합니다
}
}
new Test;
?>
어떤 경우든, 우리가 하나의 트레이트 메서드를 사용하도록 지정하면
두 번째 트레이트의 메서드는 접근할 수 없게 됩니다.
as 키워드를 통해 이름을 변경하여 두 번째 트레이트의 메서드도 사용할 수 있습니다.
다음과 같이 말이죠:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method() + $this->method2(); // 3을 출력합니다
}
}
new Test;
?>
원한다면 첫 번째 트레이트의 메서드 이름도 변경할 수 있습니다:
<?php
class Test
{
use Trait1, Trait2 {
Trait1::method insteadof Trait2;
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2(); // 3을 출력합니다
}
}
new Test;
?>
as 키워드를 insteadof를 통한 주요 메서드 정의 없이
사용할 수는 없으며, 이렇게 하면 오류가 발생합니다:
<?php
// 이 클래스는 오류를 발생시킵니다:
class Test
{
use Trait1, Trait2 {
Trait1::method as method1;
Trait2::method as method2;
}
public function __construct()
{
echo $this->method1() + $this->method2();
}
}
new Test;
?>
Trait1, Trait2, Trait3라는 이름의
트레이트 3개를 만드세요.
첫 번째 트레이트에는 1을 반환하는 메서드 method가,
두 번째 트레이트에는 2을 반환하는 동일한 이름의 메서드가,
세 번째 트레이트에는 3을 반환하는 동일한 이름의 메서드가 있도록 하세요.
우리가 만든 세 트레이트를 모두 사용하는 클래스 Test를 만드세요.
이 클래스에 연결된 트레이트 메서드들의 결과 합계를 반환하는
메서드 getSum를 만드세요.