Enumeration methods
Enumeration methods
Enum(Pure Enum과 Backed Enum 모두)에는 메서드를 정의할 수 있고, 인터페이스를 구현할 수도 있어요. Enum이 어떤 인터페이스를 구현한다면, 그 인터페이스에 대한 타입 검사는 해당 Enum의 모든 case를 통과시켜 줘요.
<?php
interface Colorful
{
public function color(): string;
}
enum Suit implements Colorful
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
// Fulfills the interface contract.
public function color(): string
{
return match ($this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
// Not part of an interface; that's fine.
public function shape(): string
{
return "Rectangle";
}
}
function paint(Colorful $c)
{
print $c->color() . "\n";
}
paint(Suit::Clubs); // Works
print Suit::Diamonds->shape(); // prints "Rectangle"
이 예시에서 Suit의 네 case 인스턴스는 모두 color()와 shape() 두 메서드를 갖고 있어요. 호출하는 코드나 타입 검사 입장에서는 다른 일반 객체 인스턴스와 똑같이 동작해요.
Backed Enum의 경우 인터페이스 선언은 backing type 선언 뒤에 와요.
<?php
interface Colorful
{
public function color(): string;
}
enum Suit: string implements Colorful
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
// Fulfills the interface contract.
public function color(): string
{
return match ($this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
}
메서드 안에서는 $this 변수가 정의되며, 이 변수는 해당 Case 인스턴스를 가리켜요.
메서드는 얼마든지 복잡하게 만들 수 있지만, 실제로는 보통 정적 값을 반환하거나 $this에 대해 match (control-structures.match.php)를 써서 case마다 다른 결과를 돌려주는 방식이 일반적이에요.
참고로 이런 경우에는 Red와 Black 값을 가진 SuitColor Enum 타입을 따로 정의해서 그 값을 반환하는 게 더 좋은 데이터 모델링 방법이에요. 다만 그렇게 하면 예시가 복잡해지니까 여기서는 생략했어요.
위 계층 구조는 논리적으로 다음 클래스 구조와 비슷해요(실제로 실행되는 코드는 아니에요).
<?php
interface Colorful
{
public function color(): string;
}
final class Suit implements UnitEnum, Colorful
{
public const Hearts = new self('Hearts');
public const Diamonds = new self('Diamonds');
public const Clubs = new self('Clubs');
public const Spades = new self('Spades');
private function __construct(public readonly string $name) {}
public function color(): string
{
return match ($this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
public function shape(): string
{
return "Rectangle";
}
public static function cases(): array
{
// Illegal method, because manually defining a cases() method on an Enum is disallowed.
// See also "Value listing" section.
}
}
메서드는 public, private, protected 어느 것이든 쓸 수 있어요. 다만 상속이 허용되지 않기 때문에 실제로는 private와 protected가 동일하게 동작해요.