Enumeration methods

Оновлено: 09.05.2023

Зчислення (як чисті, так і підкріплені) можуть містити методи, а також можуть реалізовувати інтерфейси. Якщо зчислення реалізує інтерфейс, то будь-яка перевірка типу для цього інтерфейсу також прийме всі випадки цього зчислення.

<?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) { ... }

paint(Suit::Clubs);  // Works

print Suit::Diamonds->shape(); // prints "Rectangle"
?>

У цьому прикладі всі чотири екземпляри Suit мають два методи, color() та shape(). Що стосується коду виклику та перевірки типів, вони поводяться так само, як і будь-який інший екземпляр об'єкта.

У перерахуванні з підкріпленням оголошення інтерфейсу йде після оголошення типу підкріплення.

<?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, щоб забезпечити різні результати для різних випадків.

Зауважте, що у цьому випадку краще було б також визначити тип перерахування SuitColor зі значеннями Red і Black і повернути його замість цього. Однак це ускладнило б цей приклад.

Наведена вище ієрархія логічно схожа на наступну структуру класів (хоча це не є фактичним кодом, який виконується):

<?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.
    }
}
?>

Методи можуть бути публічними, приватними або захищеними, хоча на практиці поняття "приватний" і "захищений" є рівнозначними, оскільки успадкування не допускається.