Developer

【PHP応用】インターフェース
2021.07.31
Lv1

【PHP応用】インターフェース

【PHP応用】インターフェース

1.インターフェースは「interface」キーワードを使って定義する。
2.インターフェースは実装を含むメソッドは定義できない。定数は定義できる。
3.インターフェースは多重実装が可能。

インターフェースとは

インターフェースは実装しなければいけないメソッドを定義するものです。
クラスはインターフェースをimplements演算子で「実装する」と指定することで、
そのインターフェースで定義づけられたメソッドを実装しなければならなくなります。

その点、抽象クラスと似ている部分もありますが、
抽象クラスには具象メソッドも定義することができましたが、
インターフェースはメソッドの実装は全く定義できません。
また、インターフェイス内で定義される全てのメソッドはpublicである必要があります。
省略した場合は自動的にpublicになります。

インターフェース(と抽象クラス)が、コードの基本設計にあたり、
具象クラスが、コードの詳細設計にあたります。
ですので、最初からクラスを書くのでなく、
インターフェースを先に書くことで、
細かい実装に拘泥せず、必要なコードの大枠を定義できる利点があります。

インターフェースの定義構文

interface インターフェース名{
    public function メソッド名();
}

インターフェースを実装するクラスの構文

class クラス名 implements インターフェース名{

}

インターフェースの継承

interface 子インターフェース名 extends 親インターフェース名{

}

インターフェースと定数

インターフェースでは定数を定義することができます。
しかし、その定数を、実装先のクラスでオーバーライドできません。

<?php
interface Constants{
    const x = 100;
}

class Constants_ implements Constants{
    const x = 1;
}

echo (new Constants_())->x;
?>

インターフェースのサンプル

interface If2_3_1{
    const X = "xxx";
    function if_x();
}

class Sample2_3_1 implements If2_3_1{
    //const X = "xxx2";
    function if_x(){
        echo self::X;
    }
}
$s = new Sample2_3_1;
$s->if_x();

インターフェースの多重実装

インターフェースは多重実装が可能です。
その場合、implementsに定義した全てのインターフェースで
宣言されているメソッドを実装する必要があります。

interface If2_3_2_1{
    function a();
}
interface If2_3_2_2{
    function b();
}
class Sample2_3_2 implements If2_3_2_1, If2_3_2_2{
    function a(){
        echo "a";
    }
    function b(){
        echo "b";
    }
}

補足

PHPでは多重継承(複数のクラスの継承)はできません。
その代替として、多重実装を使います。
たとえば、CSV可能なクラスと、JSON可能なクラスというクラス定義をして、
そのあとに、CSVにもJSONにもできるクラスを用意しようとしても、
できません。
代わりに、CSVにできるインターフェースと、JSONにできるインターフェースを用意し、
目的のクラスに、2つのインターフェースを多重実装させれば、同じ目的が達成できます。

<?php
interface CSVable
{
    function toCSV();
}

interface JSONable
{
    function toJSON();
}

class Product implements CSVable, JSONable
{
    public function __construct(int $id, String $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
    
    public function toCSV()
    {
        $value = $this->id.",".$this->name;
        
        return $value;
    }
    
    public function toJSON()
    {
        $candidate = json_encode($this);
        
        if($candidate === false)
        {
            return "{}";
        }
        
        return $candidate;
    }
    
} 

$product = new Product(1, "PC");
echo "CSV : ".$product->toCSV()."</br>";
echo "JSON : ".$product->toJSON()."</br>";
?>

インターフェースと抽象クラスの併用

以下のように、抽象クラスを継承し、インターフェースを実装したクラスを定義することも可能です。

interface IF2_3_3{
    function a();
    function c();
}
abstract class Abs2_3_3{
    abstract function a();
    function b(){
        echo "b";
    }
}
class Sample2_3_3 extends Abs2_3_3 implements IF2_3_3{
    function a(){
        echo "a";
    }
    function c(){
        echo "c";
    }
}
$s = new Sample2_3_3();
$s->a();
$s->b();
$s->c();