Amazonランキング大賞2018

クラス

クラス定義

コード
class クラス名{

    //クラスプロパティ(クラス自身が持つプロパティ staticをつける)
    //クラス内で利用する場合は self::$変数名
    //クラス外から利用する場合は クラス名::$変数名
    public static $変数名;
    //定数の場合は$もstaticもつけない self::定数名、クラス名::定数名
    //staticが無くてもstaticな存在になるし、つけるとエラー
    public const 定数名 = 値;

    //プロパティ
    public $変数名;    //プロパティに初期値は設定できるが、計算式は書けない

    //コンストラクタ 不要なら省略
    //コンストラクタはひとつしか定義出来ない。
    //引数違いのコンストラクタは用意できないため、
    //引数の初期値、可変個引数を使ってカバーする
    function __construct($変数名){    //アンダーバーは2個
        //継承クラスの場合、親クラスのコンストラクタは自動コールされない
        //必要に応じて自分で呼び出す必要がある。
        parent::__construct();    //親クラスのコンストラクタ呼び出し
    }

    //デストラクタ 不要なら省略
    //オブジェクトを参照するリファレンスがひとつもなくなったときにコールされる。
    //あるいはスクリプト終了時に順不同でコールされる
    function __destruct(){
        //デストラクタには戻り値も引数も存在しない
        
        //継承クラスの場合、親クラスのデストラクタは自動コールされない
        //必要に応じて自分で呼び出す必要がある。
        parent::__destruct();    //親クラスのデストラクタ呼び出し
    }

    //メソッド
    public function メソッド名(){
    }

    //クラスメソッド(クラス自身が持つメソッド staticをつける)
    //クラスメソッドをクラス内で呼び出す場合は self::メソッド名();
    //クラス外から呼び出す場合は クラス名::メソッド名();
    public static function メソッド名(){
    }
}

$myClass = new クラス名();
$myClass2 = new クラス名;    //括弧を省略できる

プロパティ、メソッドにアクセスする場合は ->演算子
メソッド内で自分のプロパティにアクセスする場合は $this->プロパティ名
$thisを省くとローカル変数へのアクセスとみなされる

class Sample{
    public const MEMBER_MAX = 5;
    public $id = "A12345";
    public $num = 100;

    function __construct($num){
        $this->num = $num;
    }

    function __destruct(){
        echo "デストラクタがコールされました id=", $this->id, PHP_EOL;
    }

    public function AddNum($a, $b){
        return $a + $b + $this->num;
    }
}

$myClass = new Sample();    //引数ありのコンストラクタが定義済みなので、これはエラー
$myClass = new Sample(200);    //引数ありの生成
echo nl2br($myClass->id . PHP_EOL);
echo $myClass->AddNum(10, 20);
参考 クラスの基礎PHP.net 参考 コンストラクタとデストラクタPHP.net

クラスのアクセス修飾子

クラスのプロパティは必ずアクセス修飾子が必要
クラスのメソッドは省略可能だが、省略した場合はpublicとみなされる

public どこからでもアクセス可能
protected 定義したクラス自身と継承した子クラス、および親クラスからアクセス可能
private 定義したクラス内のみでアクセス可能

クラスを単一のファイルに独立させる

その場限りで終わらないクラスはクラスファイルとして独立させる

クラス名.php
Javaのように1クラス1ファイルのルールはない。

Sample.php
<?php
class Sample{
    public const MEMBER_MAX = 5;
    public $id = "A12345";
    public $num = 100;

    function __construct($num){
        $this->num = $num;
    }

    function __destruct(){
        echo "デストラクタがコールされました id=", $this->id, PHP_EOL;
    }

    public function AddNum($a, $b){
        return $a + $b + $this->num;
    }
}
//    ?>    PHPコードだけのファイルは終了タグを書かない

参考:外部ファイルのコードを読み込む

外部ファイルのコードを読み込む include, require

include(ファイル名)
include_once(ファイル名)
require(ファイル名)
require_once(ファイル名)

include 読み込みに失敗した場合 warning を発行する
require 読み込みに失敗した場合 fatal error を発行する
xxx_once 既に同ファイルが読み込まれている場合は、読み込まない

クラスファイルの読み込みなど、殆どのケースは require_once で済むはず。

コード
<?php
    require_once("Sample.php");
?>

クラスの継承

コード
class 子クラス名 extends 親クラス名 {

    //コンストラクタ 不要なら省略
    //親クラスのコンストラクタは自動コールされない
    //必要に応じて自分で呼び出す必要がある。
    function __construct(){
        parent::__construct();    //親クラスのコンストラクタ呼び出し
    }

    //デストラクタ 不要なら省略
    //継承クラスの場合、親クラスのデストラクタは自動コールされない
    //必要に応じて自分で呼び出す必要がある。
    function __destruct(){
        parent::__destruct();    //親クラスのデストラクタ呼び出し
    }

}

継承の禁止

クラス定義に final をつける

コード
final class Sample{
}

これでSampleクラスは継承で使うことはできなくなる。

変数、メソッドのオーバーライド

親クラスと同名の変数、メソッドを子クラスで再定義すれば、上書きできる。
ただし、親クラスが変数をprivateで定義していた場合、子クラスからはアクセス出来ないので、オーバーライドしようとしても、結果的には親クラスと子クラスに両方存在することになる。

オーバーライドしたメソッドの中で、オーバーライド前の親クラスのメソッドを呼び出すことも出来る
一部分だけを追加拡張したい場合に便利。
parent::メソッド名();

オーバーライドを禁止にしたい場合は、親クラス側で変数、メソッドにfinalをつける
final function 〜
final public $変数名

トレイト 多重継承の代用

PHPでは多重継承が出来ない。
その代用として、使いまわすプロパティ、メソッドをtraitという形でまとめ、それをclassで「使います」と宣言することでコードの再利用が出来るようになっている。

トレイトで出来ることはプロパティとメソッドの定義

コード
trait トレイト名{
    //プロパティ定義

    //メソッド定義
}

トレイトは親クラスを継承して作ることも出来る

コード
trait トレイト名 extends 親クラス{
    //プロパティ定義

    //メソッド定義
}


trait TestTrait{
    protected $number;    //プロパティ

    public function GetNumber(){    //メソッド
        return $this->number;
    }
}

使いたいクラスで use で宣言する
class Sample(){
    use TestTrait;
}

Sampleクラスでは TestTrait で定義されたプロパティ、メソッドをそのまま使える。

複数のtraitを使う場合は、
use トレイト名, トレイト名, トレイト名;
という形で宣言できる。

トレイトもクラス同様、ファイル単体に抜き出したほうが良い。

複数トレイト使用による名称衝突の解決

複数のトレイトを使用するとメンバー名が衝突する場合がある。
解決方法は以下の2つ。

  1. insteadof演算子で、どのトレイトのメンバーを使用するか指定する。
  2. as演算子で別名をつける。
コード
class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}
参考 トレイトPHP.net

インターフェース

インターフェースはクラスで実装すべきメソッドを規格として定めるもの。
インターフェースはメソッドと定数を定義できる。
メソッドは名前と引数の形式だけを定義し、機能の実装は行わない。
アクセス修飾子はpublicのみ(または省略してpublic扱いにする)

コード
interface インターフェース名{
    const 定数 = 値;
    function 関数名(引数);
}

インターフェースを継承したインターフェースも作れる

コード
interface 子インターフェース名 extends 親インターフェース名{
    const 定数 = 値;
    function 関数名(引数);
}

クラスでインターフェースを採用する場合はimplementsを使う

コード
class クラス名 implements インターフェース名, インターフェース名{
}

class クラス名 extends 親クラス名 implements インターフェース名, インターフェース名{
}
参考 オブジェクト インターフェイスPHP.net

抽象クラス abstract

抽象メソッドにはpublic, protected, privateを指定できる
(省略した場合はpublic)
抽象クラスは普通のクラスに継承して使用する。

コード
abstract class 抽象クラス名{
    abstract function 抽象メソッド名(引数);

    //通常のメソッド
    //インターフェースと違い、通常のメソッドの機能実装を行える
    //子クラスに移譲したいものだけをabstractをつけて宣言だけを行う。
    function メソッド名(引数){
        ;
    }

    //通常プロパティも宣言できる
    //抽象プロパティというのは無い。
    public $number = 0;
}

class クラス名 extends 抽象クラス名{
    //抽象クラスでabstract宣言されたメソッドを全て実装しなければならない
}
参考 クラスの抽象化PHP.net