【PHP】静的(static)メンバと動的(インスタンス)メンバの違いについて解説します。

PHP

【PHP】静的(static)メンバと動的(インスタンス)メンバの違いについて解説します。

なやむくん
よく見る「static」の記述の意味を知りたい…。
なやむさん
静的メンバと動的メソッドの違いについて理解ができない…。

などの疑問や悩みを解決してまいります。

静的メンバ(static)とは

クラスに属するプロパティやメソッドそれぞれにstaticキーワードを記述したものを静的メンバといいます。

静的メンバは、インスタンスを生成しなくてもクラスの内部・外部から直接アクセスできるようになります。

ポイント

  1. オブジェクトを生成せずにアクセス可能
    クラスのインスタンスを作成する必要がなく、クラス名を使って直接アクセスします。

  2. クラス全体で共有される
    静的プロパティやメソッドは、すべてのオブジェクトで共通のデータを保持します。
    インスタンスごとに異なるデータを持つ通常のプロパティとは異なります。

  3. self::の使用
    静的メンバにアクセスする場合、self::を使います。self::は現在のクラスを指します。
みつた
::(ダブルコロン)は、スコープ定義演算子ともいいます。

静的プロパティの例

以下のコードでは、$countを静的プロパティとしたいので、staticキーワードを記述しています。

class MyClass {
    // 静的プロパティ
    public static $count = 0;
}

// クラス外から静的プロパティにアクセスして変更
echo MyClass::$count; // 0
MyClass::$count++;    // 静的プロパティの値をインクリメント
echo MyClass::$count; // 1

静的プロパティとなった$countは、クラス外からアクセスが可能となりますので、クラス名::静的プロパティでアクセスすることができます。

静的メソッドの例

以下のコードのように、クラス内で静的メンバにアクセスする場合self::を使用します。

class MyClass {
    // 静的プロパティ
    public static $count = 0;

    // 静的メソッド
    public static function increment() {
        self::$count++;
    }

    // クラス内で別の静的メソッドを呼び出す
    public static function displayCount() {
        self::increment();
        echo "Current count is: " . self::$count . "\n";
    }
}

// クラス外からの静的メソッド呼び出し
MyClass::displayCount();  // Current count is: 1
MyClass::displayCount();  // Current count is: 2
みつた
このようにstaticキーワードを使うことでインスタンスを生成しなくても、簡単にクラスメンバにアクセスできる手軽さが魅力ですね!

self::とstatic::とparent::

静的メンバにアクセスする方法として、self::を解説しましたが、self::以外にもstatic::parent::があります。

それぞれの役割について解説していきます。

self::

self::は、定義されているクラス自身を指し、クラス内でそのクラスの静的メンバにアクセスするために使用されます。

これは現在のクラスから直接呼び出され、継承されても常にそのクラス内で解決されます。

class A {
    public static function who() {
        echo "I am A";
    }

    public static function test() {
        self::who(); // self::を使うと現在のクラスのwho()を呼び出す
    }
}

class B extends A {
    public static function who() {
        echo "I am B";
    }
}

B::test(); // "I am A" と出力される

現在のクラスのwho()を呼び出すため、出力結果は「I am A」となります。

static::

static::は、遅延静的束縛(Late Static Binding)を使用します。

これは、実際に呼び出しが行われるクラス(実行時のクラス)を指し、継承関係のあるクラスで動的にメソッドやプロパティを参照するのに適しています。

遅延静的束縛とは

クラスを継承した場合に、実行時に呼び出し元のクラスに基づいてメソッドやプロパティを解決する仕組みです。

クラス継承において、静的メソッドやプロパティを扱う際、self::を使うと「そのメソッドが定義されたクラス」に基づいてメソッドやプロパティが参照されますが、継承関係のあるクラスで子クラスのメソッドを呼び出したい場合にはstatic::を使用します。

なやむくん
うーん、難しいです。
class A {
    public static function who() {
        echo "I am A";
    }

    public static function test() {
        static::who(); // static::を使うと実行時のクラスのwho()を呼び出す
    }
}

class B extends A {
    public static function who() {
        echo "I am B";
    }
}

B::test(); // "I am B" と出力される

上記のコードは、先のself::の解説で使用したものほとんど同じで、違う箇所はself::static::に変更したという部分だけです。

self::は「メソッドが定義されたクラス」に基づいてメソッドを解決しますが、static::は「メソッドを呼び出したクラス(実行時のクラス)」に基づいてメソッドを解決します。

遅延静的束縛のポイント

定義されたクラスではなく、実行時のクラスに基づく

よろこびくん
なるほど!理解しましたー!

parent::

parent::は、親クラスのメソッドやプロパティを呼び出す際に使用されます。

子クラスから親クラスのメソッドをオーバーライドしている場合、親クラスの元のメソッドを呼び出すために使われます。

class A {
    public static function who() {
        echo "I am A";
    }
}

class B extends A {
    public static function who() {
        echo "I am B";
    }

    public static function test() {
        parent::who(); // parent::を使って親クラスのメソッドを呼び出す
    }
}

B::test(); // "I am A" と出力される

parent::who()は、子クラス内から呼び出されても、親クラスのwho()を実行してくれます。

self::parent::static::それぞれ特徴についての比較表です。

特徴self::static::parent::
参照するクラス定義されたクラス(メソッドが定義されたクラス)実行時のクラス(呼び出し元のクラス)親クラス
オーバーライドの影響受けない(親のメソッドを常に呼び出す)受ける(オーバーライドされたメソッドを呼び出す)受けない(常に親のメソッドを呼び出す)
用途自クラス内で静的メソッドやプロパティを呼び出す時遅延静的束縛を利用して、実行時のクラスのメソッドを呼び出す時親クラスのメソッドを呼び出す時
実行時の挙動常に定義されたクラスのメソッドが呼び出される実行時に呼び出されたクラスのメソッドが呼び出される常に親クラスのメソッドが呼び出される
self::parent::static::の比較表

動的メンバ(インスタンス)とは

クラスから生成したインスタンス(オブジェクト)に関連付けられるプロパティやメソッドのことを動的メンバといいます。

動的メンバは、インスタンスが生成されていないと使用することができないので注意が必要です。

ポイント

  1. インスタンス(オブジェクト)ごとに独立
    動的メンバは、各インスタンスで個別に保持されるため、複数のオブジェクト間で異なる状態を持つことができます。

  2. インスタンス生成後にアクセス可能
    動的メンバにアクセスするためには、クラスのインスタンスを生成してから、そのインスタンスを介してプロパティやメソッドにアクセスします。

  3. $thisキーワードを使用してアクセス
    クラス内で動的メンバにアクセスする際は、$thisを使ってそのインスタンスのプロパティやメソッドを参照します。

動的プロパティの例

以下のコードのように、動的プロパティにアクセスする場合は、インスタンスを生成する必要があります。

class MyClass {
    // 動的プロパティ
    public $count = 0;
}

// オブジェクトを生成
$object1 = new MyClass();
$object2 = new MyClass();

// 動的プロパティへのアクセス
$object1->count = 5;
$object2->count = 10;

echo $object1->count; // 5
echo $object2->count; // 10

外部から動的メンバにアクセスする場合は、インスタンス名->動的プロパティでアクセスします。

動的メソッドの例

クラス内で動的メンバにアクセスする場合は、$thisを使用します。

class MyClass {
    // 動的プロパティ
    public $count = 0;

    // 動的メソッド
    public function increment() {
        $this->count++;
    }

    // 動的メソッド
    public function displayCount() {
        echo "Current count is: " . $this->count . "\n";
    }
}

// オブジェクトを生成
$object1 = new MyClass();
$object2 = new MyClass();

// オブジェクトごとにメソッドを呼び出し
$object1->increment();
$object1->displayCount();  // Current count is: 1

$object2->increment();
$object2->increment();
$object2->displayCount();  // Current count is: 2

まとめ

静的メンバと動的メンバの違いについて理解できましたでしょうか。

静的メンバはクラス全体で共通のデータや機能を提供し、動的メンバは各インスタンスに固有のデータを管理します。

それぞれの特性を理解することで、効率的なクラス設計が可能となりますので、ぜひ参考にしてください。

参考記事

PHP: クラスの基礎 - Manual

PHP: static キーワード - Manual

PHP: スコープ定義演算子 (::) - Manual

  • この記事を書いた人
  • 最新記事

みつた

完全未経験&異業種から30歳の年でIT企業に転職。

Web系開発言語が好き。
どちらかというとバックエンドよりもフロントエンドが好き(現時点では…)

最近はサウナと観葉植物にハマっている。
野球が好きで一応投手。

-PHP