列挙型とメソッド

列挙型では、(Pure Enum と Backed Enum ともに) メソッドを含めることもできますし、 インターフェイスを実装することもできます。 列挙型がインターフェイスを実装する場合、 そのインターフェイスでの型チェックは、 実装した列挙型の全ての case で有効です。

<?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::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}

// インターフェイスの一部ではないが、正しいコード
public function shape(): string
{
return
"Rectangle";
}
}

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

paint(Suit::Clubs); // 動作します

print Suit::Diamonds->shape(); // "Rectangle" と表示
?>

上記の例の Suit の4つのインスタンスは、 全てふたつのメソッド color()shape() を持ちます。 コードの呼び出しと型チェックに限れば、 これらのメソッドは他のオブジェクトのインスタンスと全く同じ振る舞いをします。

Backed Enum の場合、 インターフェイスの宣言は依存する型の宣言の直後に置きます。

<?php

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

enum
Suit: string implements Colorful
{
case
Hearts = 'H';
case
Diamonds = 'D';
case
Clubs = 'C';
case
Spades = 'S';

// インターフェイスの規約を満たすための実装
public function color(): string
{
return match(
$this) {
Suit::Hearts, Suit::Diamonds => 'Red',
Suit::Clubs, Suit::Spades => 'Black',
};
}
}
?>

メソッドの内部では、 変数 $this が定義され、 case のインスタンスを参照します。

メソッドには任意の複雑な処理を記述できますが、 実際、通常は静的な値を返したり、 case 毎に異なる結果を提供するために match$this と共に使う処理を行います。

この場合は、Red と Black の値を持ち、 それらを返す SuitColor という列挙型を定義する方が、 より良いデータモデリングのプラクティスであることにも注意して下さい。 しかし、そうすると上の例が複雑になるでしょう。

上で示した階層は、論理的には次のようなクラス階層に似ています (しかし、以下のコードは実際には動作しません):

<?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
{
// 不正なメソッド。列挙型では、手動で cases() メソッドを定義できないからです。
// "値のリスト" のページも参照ください。
}
}
?>

メソッドには public, private, protected が指定できますが、 列挙型では実際 private と protected は同じものです。 なぜなら、継承が許されていないからです。

add a note add a note

User Contributed Notes 1 note

up
0
iloveyii at yahoo dot com
1 year ago
Just to complete the function shape in the above neat example:

<?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
match($this) {
              
Suit::Hearts => '❤️',
              
Suit::Diamonds => '💎',
              
Suit::Clubs => '♣️',
              
Suit::Spades => ' ♠️'
          
};
      
    }
}

echo
Suit::Diamonds->shape();
echo
PHP_EOL;
echo
Suit::Clubs->shape();
To Top