Методы перечислений

Перечисления (как чистые перечисления, так и типизированные перечисления) могут содержать методы и могут реализовывать интерфейсы. Если перечисление реализует интерфейс, то любая проверка типа для этого интерфейса также будет принимать все варианты этого перечисления.

<?php

interface Colorful
{
    public function 
color(): string;
}

enum Suit implements Colorful
{
    case 
Hearts;
    case 
Diamonds;
    case 
Clubs;
    case 
Spades;

    
// Выполняет интерфейсный контракт.
    
public function color(): string
    
{
        return 
match($this) {
            
Suit::HeartsSuit::Diamonds => 'Красный',
            
Suit::ClubsSuit::Spades => 'Чёрный'
        
};
    }

    
// Не является частью интерфейса; хорошо.
    
public function shape(): string
    
{
        return 
"Rectangle";
    }
}

function 
paint(Colorful $c) { ... }

paint(Suit::Clubs);  // Работает

print Suit::Diamonds->shape(); // выведет "Rectangle"
?>

В этом примере у всех четырёх экземпляров Suit есть два метода: color() и shape(). Что касается вызывающего кода и проверки типов, они ведут себя точно так же, как и любой другой экземпляр объекта.

В типизированных перечислениях объявление интерфейса идёт после объявления типа.

<?php
interface Colorful
{
    public function 
color(): string;
}

enum Suitstring implements Colorful
{
    case 
Hearts 'H';
    case 
Diamonds 'D';
    case 
Clubs 'C';
    case 
Spades 'S';

    
// Выполняет интерфейсный контракт.
    
public function color(): string
    
{
        return 
match($this) {
            
Suit::HeartsSuit::Diamonds => 'Красный',
            
Suit::ClubsSuit::Spades => 'Чёрный'
        
};
    }
}
?>

Внутри метода определяется переменная $this, которая ссылается на экземпляр варианта.

Методы могут быть сколь угодно сложными, но на практике обычно возвращают статическое значение или match для $this, чтобы предоставить разные результаты для разных случаев.

Обратите внимание, что в этом случае было бы лучше также определить тип перечисления SuitColor со значениями Red и Black и вернуть его вместо этого. Однако это усложнило бы этот пример.

Вышеупомянутая иерархия логически похожа на следующую структуру классов (хотя это не фактический исполняемый код):

<?php
interface Colorful
{
    public function 
color(): string;
}

final class 
Suit implements UnitEnumColorful
{
    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::HeartsSuit::Diamonds => 'Красный',
            
Suit::ClubsSuit::Spades => 'Чёрный'
        
};
    }

    public function 
shape(): string
    
{
        return 
"Прямоугольник";
    }

    public static function 
cases(): array
    {
        
// Недопустимый метод, поскольку определение метода cases() в перечислениях вручную запрещено.
        // Смотрите также раздел "Список значений".
    
}
}
?>

Методы могут быть общедоступными, закрытыми или защищёнными, хотя на практике закрытые и защищённые эквивалентны, поскольку наследование не допускается.

add a note add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top