Menu
Coddy logo textTech

여러 트레이트 사용하기

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

단일 트레이트(trait)도 유용하지만, 진정한 힘은 하나의 클래스에 여러 트레이트를 결합할 때 나타납니다. PHP를 사용하면 필요한 만큼 많은 트레이트를 포함할 수 있으며, 이를 통해 클래스에 여러 소스의 기능을 동시에 부여할 수 있습니다.

여러 개의 트레이트(trait)를 사용하려면, use 키워드 뒤에 쉼표로 구분하여 나열하면 됩니다:

<?php
trait Timestampable {
    public function getTimestamp(): string {
        return date('Y-m-d H:i:s');
    }
}

trait Identifiable {
    private string $id;
    
    public function generateId(): void {
        $this->id = uniqid('id_');
    }
    
    public function getId(): string {
        return $this->id;
    }
}

class Post {
    use Timestampable, Identifiable;
    
    public function __construct(public string $title) {
        $this->generateId();
    }
}

$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();

출력:

id_6789abc123 - 2024-01-15 10:30:00

Post 클래스는 이제 두 트레이트의 메서드를 모두 가집니다. 각 트레이트는 고유한 기능을 제공합니다 - Timestampable은 시간 관련 메서드를 제공하고, Identifiable은 고유 ID를 처리합니다. 이 방식은 각 트레이트가 단일 책임에 집중하도록 유지하여 코드를 더 모듈화하고 재사용 가능하게 만듭니다.

두 개의 트레이트(trait)가 같은 이름의 메서드(method)를 가지고 있으면 어떻게 될까요? 이는 다음 레슨에서 살펴볼 충돌 상황입니다.

challenge icon

챌린지

쉬움

여러 개의 trait를 결합하여 제품에 가격 책정 및 재고 관리 기능을 모두 부여하는 제품 관리 시스템을 구축해 보겠습니다. 각 trait는 단일 책임을 처리하며, 제품 클래스는 두 trait로부터 기능을 얻게 됩니다.

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

  • Priceable.php — 가격 책정 기능을 처리하는 Priceable이라는 trait를 생성합니다. 이 trait는 다음을 포함해야 합니다:
    • private 속성 $price (float)
    • 가격을 저장하는 setPrice(float $price) 메서드
    • 가격을 반환하는 getPrice() 메서드
    • 가격을 소수점 2자리까지 포함된 "$[price]" 형식으로 반환하는 getFormattedPrice() 메서드
  • Stockable.php — 재고를 관리하는 Stockable이라는 trait를 생성합니다. 이 trait는 다음을 포함해야 합니다:
    • private 속성 $stock (integer)
    • 재고 수량을 저장하는 setStock(int $quantity) 메서드
    • 현재 재고를 반환하는 getStock() 메서드
    • 재고가 0보다 크면 true를, 그렇지 않으면 false를 반환하는 isInStock() 메서드
  • main.php — 두 trait 파일을 포함하고 PriceableStockable trait를 모두 사용하는 Product 클래스를 생성합니다. 생성자 프로모션(constructor promotion)을 사용하여 public $name 속성을 정의하세요. 생성자는 가격과 재고 수량도 인자로 받아야 하며, trait 메서드를 사용하여 이를 설정해야 합니다.

    제품 이름, 가격, 재고 수량이라는 세 가지 입력을 받게 됩니다. 이 값들로 제품을 생성하고 다음 네 줄을 출력하세요:

    • 제품 이름
    • 형식화된 가격 (getFormattedPrice() 사용)
    • 재고 수량
    • 재고가 있는 경우 "Available", 없는 경우 "Out of stock"

이것은 여러 trait가 어떻게 함께 작동하는지 보여줍니다. Product 클래스는 한 trait에서 가격 책정 기능을, 다른 trait에서 재고 관리 기능을 얻어 각 관심사를 깔끔하게 분리하면서도 모든 기능을 갖춘 제품으로 결합합니다.

치트 시트

클래스에서 여러 개의 트레이트(trait)를 사용하려면, use 키워드 뒤에 쉼표로 구분하여 나열합니다:

<?php
trait Timestampable {
    public function getTimestamp(): string {
        return date('Y-m-d H:i:s');
    }
}

trait Identifiable {
    private string $id;
    
    public function generateId(): void {
        $this->id = uniqid('id_');
    }
    
    public function getId(): string {
        return $this->id;
    }
}

class Post {
    use Timestampable, Identifiable;
    
    public function __construct(public string $title) {
        $this->generateId();
    }
}

$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
// 출력: id_6789abc123 - 2024-01-15 10:30:00

각 트레이트는 클래스에 고유한 기능을 제공합니다. 이러한 방식은 각 트레이트가 단일 책임에 집중하도록 유지하여, 코드를 더욱 모듈화하고 재사용 가능하게 만듭니다.

직접 해보기

<?php
require_once 'Priceable.php';
require_once 'Stockable.php';

// TODO: Priceable 및 Stockable 트레이트를 모두 사용하는 Product 클래스를 생성하세요.
// public $name 속성에 대해 생성자 프로모션(constructor promotion)을 사용하세요.
// 생성자는 name, price, stock을 인자로 받아야 하며, 트레이트 메서드를 사용하여 price와 stock을 설정해야 합니다.

class Product {
    // TODO: 여기서 트레이트를 사용하세요.

    // TODO: $name에 대한 생성자 프로모션을 포함한 생성자를 구현하고,
    // 트레이트 메서드를 사용하여 price와 stock을 설정하세요.
}

// 입력 읽기
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));

// TODO: 입력된 값으로 Product 인스턴스를 생성하세요.

// TODO: 제품 이름을 출력하세요.
// TODO: getFormattedPrice()를 사용하여 형식화된 가격을 출력하세요.
// TODO: 재고 수량을 출력하세요.
// TODO: 재고가 있으면 "Available"을, 없으면 "Out of stock"을 출력하세요.
?>
quiz icon실력 점검

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

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