서로 상속관계가 없는 여러 클래스에서 공통된 기능을 사용하고 싶을때가 있는데 예를들어 로그기록(logger), 파일업로드(uploader) 등 같은 기능들은 User, Product 다양한 클래스에서 필요할수있음..
이때 트레이트를 사용하면 상속 관계와 무관하게 원하는 클래스에서 사용 할 수 있습니다.
음.. 클래스에 필요한 기능들을 플러그인을 하는 것과 비슷합니다.
extends(상속) vs use(트레이트) extends (상속): is a 관계 (자식 is a 부모). 클래스 간의 수직적 계층 관계를 형성합니다. (예: Cat is an Animal) use (트레이트): can do 관계 (클래스 can do 기능). 클래스에 특정 행동/능력을 수평적으로 추가합니다. (예: User can do Logging)
1. 트레이트 사용
트레이트는 tarit 키워드로 정의하고 클래스에서는 user 키워드로 가져와 사용합니다.
<?php
// 1. 재사용할 기능을 담은 트레이트를 정의합니다.
traitSharable
{
publicfunctionshare(string$item): string
{
return"Sharing item: '{$item}' to social media.";
}
}
// 2. 클래스에서 'use' 키워드로 트레이트를 포함시킵니다.
classPost
{
useSharable; // Sharable 트레이트의 모든 메소드를 Post 클래스에 주입
publicstring$title;
}
classPhoto
{
useSharable;
publicstring$url;
}
// 3. 이제 트레이트의 메소드를 클래스 자신의 메소드처럼 사용할 수 있습니다.
$post = newPost();
echo$post->share("My new blog post") . PHP_EOL;
$photo = newPhoto();
echo$photo->share("A picture from my vacation") . PHP_EOL;
?>
2. 여러 트레이트를 사용하거나 클래스간에 메소드 이름이 충돌 할 수 있습니다. PHP는 해결 하기 위해 규칙과 방법을 제공
<?php
traitLogger
{
publicfunctionlog(string$message): void
{
echo"[로그] {$message}". PHP_EOL;
}
}
traitNotifiable
{
publicfunctionnotify(string$message): void
{
echo"[NOTIFICATION] 이메일 전송: {$message}". PHP_EOL;
}
}
classOrder
{
// 여러 트레이트를 한 번에 사용
useLogger, Notifiable;
publicfunctionplaceOrder(): void
{
$this->log("새로운 주문이 접수되었습니다.");
// ... 주문 처리 로직 ...
$this->notify("주문이 확인 되었습니다.");
}
}
$order = newOrder();
$order->placeOrder();
?>
3. 메소드 충돌 해결
서로 다른 트레이트가 같은 이름의 메소드를 가지고 있을 때 그대로 use하면 오류가 발생합니다.
isteadof와 as키워드를 사용해 어떤 메서드를 사용할지 명시적으로 지정.
<?php
traitTraitA
{
publicfunctiondoSomething(): void
{
echo"특성 A에서 무언가를 수행 \ ". PHP_EOL;
}
}
traitTraitB
{
publicfunctiondoSomething(): void
{
echo"특성 B에서 무언가를 수행 \ ". PHP_EOL;
}
}
classMyClass
{
useTraitA, TraitB {
// TraitA의 doSomething을 사용하고, TraitB의 것은 무시함
TraitA::doSomething insteadofTraitB;
// TraitB의 doSomething 메소드는 'doSomethingFromB'라는 새 이름(별칭)으로 사용함
TraitB::doSomething as doSomethingFromB;
}
}
$obj = newMyClass();
$obj->doSomething(); // TraitA의 메소드 호출
$obj->doSomethingFromB(); // TraitB의 메소드를 새 이름으로 호출
?>
4. 가시성 변경
트레이트에서 가져온 메서드의 가시성(public, protected, private) 를 as 키워드로 변경 할 수 있습니다.