PHP

【PHP】クラスの作成方法とpublic、private、protected、$this、__construct関数の使い方

PHPのクラスの作成方法と使い方を紹介します。 また、public、private、protected、$this、__construct関数の使い方を紹介します。

この記事の目次
  1. クラス(Class)とは
  2. クラスの作り方
  3. プロパティ – 変数のアクセス範囲を指定するキーワードを付与する
  4. コンストラクタはpublicとprivateのどちらにするか
  5. PHP 8のコンストラクタプロパティ昇格
  6. $thisについて
  7. __construct関数について
  8. インスタンス化する
  9. クラスの静的メソッドstaticメソッドについて
  10. プロパティも静的にできる
  11. private staticでクラスの外から隠す
  12. 静的メソッドと通常のメソッドの使い分け

PHPのクラスの作成方法と使い方を紹介します。
また、public、private、protected、$this、__construct関数の使い方を紹介します。

先に要点をまとめます。publicはクラスの外からも使える、privateはそのクラスの中だけ、protectedはそのクラスと継承したクラスの中だけ、というアクセス範囲の指定です。
public functionのようにメソッドの前に付け、省略するとpublic扱いになります。
__constructnewしたときに自動で呼ばれる初期化用のメソッドで、$thisは「今作られたそのオブジェクト自身」を指します。
private staticのようにstaticと組み合わせると、インスタンスではなくクラス自体に属する、外から触れないプロパティやメソッドになります。

クラス(Class)とは

クラスとは、新しくオブジェクトを作成するための雛形です。
オブジェクトとは、関連する変数や関数をひとまとめにしたものです。
たとえば、Animalというクラスを作成します。
それには動物のあらゆる情報を持たせておくことができます。
意味のあるまとまりにすることで、コードの再利用性が高まったり可読性が上がります。

言葉ではわかりにくいので、以下で実際の作成方法を確認します。

スポンサーリンク

クラスの作り方

<?php
class Animal
{
    // プロパティ
    public $age;
    private $name;
    // protected $name;

    // コンストラクタ関数
    function __construct($age, $name)
    {
        // それぞれのプロパティに対して格納する
        // $this->age、つまりpublic $ageに引数の$ageを代入するという意味
        $this->age = $age;
        $this->name = $name;
    }

    // メソッド
    // publicが省略されている
    function hello() {
        echo 'hello, ' . $this->name;
    }
    private function hello2() {
        echo 'hello2, ' . $this->name;
    }
}

クラス内の変数部分のことをプロパティ、関数のことをメソッドといいます。
また、特別な関数である、コンストラクタ関数があります。
まずは、作成の手順を確認します。

プロパティ – 変数のアクセス範囲を指定するキーワードを付与する

アクセス範囲を指定するキーワードには、publicとprivateがあります。

publicにすると、クラスの外から呼び出せます。
反対に、privateの場合はクラスの外からは呼び出せません。

メソッドの場合には、publicなどをつけていないと、publicが省略されていると見なされます。
privateの場合はつける必要があります。

protectedの場合は、自クラスか、クラスを継承したクラスでのみアクセスできます。
publicとprivateの中間に位置するものです。

迷ったときは、まずprivateにしておき、クラスの外から本当に必要になったものだけpublicにします。外から自由に書き換えられる値が少ないほど、あとからクラスの中身を変えやすくなります。

コンストラクタはpublicとprivateのどちらにするか

__constructは通常publicにします(省略時もpublic)。privateにすると外からnewできなくなるため、「インスタンスを1つしか作らせたくない(シングルトン)」「生成方法を専用のstaticメソッドに限定したい」といった特別な目的があるときだけ使います。

PHP 8のコンストラクタプロパティ昇格

PHP 8.0以降は、コンストラクタの引数にアクセス修飾子を付けるだけで、プロパティの宣言と代入をまとめて書けます。

<?php
class Animal
{
    // public $age; private $name; の宣言と $this->age = $age; の代入を兼ねる
    public function __construct(
        public int $age,
        private string $name,
    ) {}
}

記事内の例は仕組みが見えるように従来の書き方にしていますが、新しく書くコードではこちらの方が短く済みます。

$thisについて

$thisは、インスタンス化されたオブジェクトのことを指し示します。
上の場合であれば、$thisはAnimalクラスをインスタンス化した$monkeyというオブジェクトを指し示します。

<?php
class Animal
{
    // プロパティ
    public $age;
    private $name;

    // コンストラクタ関数
    function __construct($age, $name)
    {
        // それぞれのプロパティに対して格納する
        // $this->age、つまりpublic $ageに引数の$ageを代入するという意味
        $this->age = $age;
        $this->name = $name;
    }

    // メソッド
    // publicが省略されている
    function hello() {
        echo 'hello, ' . $this->name;
        return $this;
    }
    function googNight() {
        echo 'Good night, ' . $this->name;
        return $this;
    }
    private function hello2() {
        echo 'hello2, ' . $this->name;
    }
}

$dog = new Animal('8', 'dog');
$dog->hello()->googNight();

上のように、$thisはインスタンスオブジェクトを指すので、
$thisをreturnすると、続けて他のメソッドを呼べます(メソッドチェーン)。

__construct関数について

__construct関数は、newでインスタンス化するとき(オブジェクトを生成するとき)に、PHPによって自動的に呼ばれる関数です。
__construct関数は、引数をとり、その引数をそれぞれのプロパティに対して格納します。

インスタンス化する

<?php
  $monkey = new Animal('10','monkey');
  echo $monkey->age;
  //   10
  echo $monkey->name;
  //   名前の方はprivateのため、fatal errorが出てアクセスできません。

//   メソッドは以下のようにして実行します。
  $monkey->hello();

new演算子でオブジェクトを作成することをインスタンス化といいます。
生成したオブジェクト、つまり上の例では$monkeyのことを、インスタンスやインスタンスオブジェクト、オブジェクトといいます。
new演算子でインスタンスオブジェクトを生成するときに、最初にコンストラクタ関数が呼ばれます。
そのとき、引数に指定した文字列が__construct関数に渡ります。

クラスの静的メソッドstaticメソッドについて

<?php
class Animal
{
    // プロパティ
    public $age;
    private $name;
    public static $like = 'eating';
    static public $dislike = 'cold';

    // コンストラクタ関数
    function __construct($age, $name)
    {
        // それぞれのプロパティに対して格納する
        // $this->age、つまりpublic $ageに引数の$ageを代入するという意味
        $this->age = $age;
        $this->name = $name;
    }

    // メソッド
    // publicが省略されている
    function hello() {
        echo 'hello, ' . $this->name;
        static::hi();
    }
    // static内では$thisが使えない
    static function hi() {
        // echo 'hi, ' . $this->name;
        echo 'hi!';
    }
    private function hello2() {
        echo 'hello2, ' . $this->name;
    }
}

$cat = new Animal('4','cat');
Animal::hi(); //一般的にはこのようにして呼び出す
$cat::hi(); //こっちでも呼び出すことは可能

staticメソッドは、クラス自体に登録するメソッドです。
functionの前にstaticキーワードを付けて作成します。
特徴としては、staticメソッド内では$thisキーワードを使えません。
メソッドをクラス側で保持しているため、インスタンスオブジェクトを指す$thisが存在しないからです。

また呼び出し方も変わり、クラス名::staticメソッドという書き方になります。
また、インスタンスオブジェクトはクラスを継承しているので、オブジェクト名::staticメソッドという形式でも呼び出せます。

メソッド内では、static::静的メソッド名と記述します。

プロパティも静的にできる

<?php

// 次の3つ書き方が可能、constも意味は同じになる
public static $like = 'eating';
public const like2 = 'sleeping';
static public $dislike = 'cold';

echo Animal::$like;
echo static::like2;
//eating
//eating

クラス内で、上のようにpublicやprivateのキーワードとstaticのキーワードはどちらが先でもいいです。
そして、上のように指定することで呼び出すことができます。

constを使う場合は、$マークは不要になります。呼び出すときも不要です。
上書きされたくない場合は、constを使います。クラス定数と通常の定数の違いはPHPの定数の使い方とconstとdefineの違いにまとめています。

private staticでクラスの外から隠す

staticにもpublic・private・protectedを付けられます。private staticにすると、クラスの外からはAnimal::$countのように触れず、クラス内のメソッドからだけ読み書きできます。「作ったインスタンスの数」のように、クラス全体で1つだけ持ちたいが外から勝手に変えられたくない値に向いています。

<?php
class Animal
{
    private static int $count = 0;   // クラスの外からは見えない

    public function __construct()
    {
        self::$count++;              // 自クラスのstaticプロパティはself::で参照する
    }

    public static function getCount(): int
    {
        return self::$count;         // 読み取り専用の窓口だけpublicにする
    }

    private static function log(string $message): void
    {
        // クラス内部だけで使う補助処理
    }
}

new Animal();
new Animal();
echo Animal::getCount(); // 2
// echo Animal::$count;  // privateのためエラー

self::はそのクラス自身を、static::は実際に呼び出されたクラス(継承先なら継承先)を指します。継承を使わないうちはself::で統一しておけば十分です。

静的メソッドと通常のメソッドの使い分け

静的メソッドを使う場合は、一般的には$thisを使うかどうかで切り分けます。
$thisを使う場合は一般的なメソッドで書く必要があります。

また静的プロパティに関しては、クラスで共通するプロパティになるため、
そのようなオブジェクトごとに値が変化しないプロパティには静的プロパティを使用します。

スポンサーリンク