コラム

staticが付いたらクラスの中に入ってはいるけど別物と考えよう

※この記事の注意事項
・できるだけ初心者の方が理解しやすいように、細かい説明は省略しております。
・最後まで読み進められるように、多少ユーモアを交えて表現していることがあります。

========================================

クラスの中でちょっと特別なstaticについて

メンバ変数もメソッドも、staticという文字が付いたら、ちょっと別物だと思った方が良いです。

クラスはインスタンス化して使うということは前回の記事で説明したけど、staticに関してはインスタンス化しなくても使えるんですよね。逆にインスタンスからは使えないんです。

どういうことかと言うと、

インスタンス化した後っていうのは、アロー演算子 -> を使って、クラスの中身を取り出すものです。

/**
 * テストクラス
 */
class test_class
{
  public $test_menber_hensu1 = 100;

  protected $test_menber_hensu2;

  public function __construct()
  {
    # code...
  }

  public function test_method($test_hikisu)
  {
    echo htmlspecialchars($test_hikisu, ENT_QUOTES);
  }
}

//クラスのインスタンス化
$instance = new test_class();

//メソッドの呼び出し
$instance->test_method('こんにちは');

//メンバ変数の呼び出し
echo $instance->test_menber_hensu1;

こんな感じで取り出すことができます。

図に書いてみると、クラスの中にメンバ変数やメソッドが内包されている状態ですね。

クラス
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
| | ̄ ̄ ̄ ̄ ̄| |
| |メンバ変数| |
| |_____| |
|        |
| | ̄ ̄ ̄ ̄ ̄| |
| |メソッド | |
| |_____| |
|________|

これがstaticになると、メンバ変数やメソッドの中ではなく、クラス直下になるイメージです。

クラス
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
| static変数  |
|        |
| staticメソッド|
|        |
| | ̄ ̄ ̄ ̄ ̄| |
| |メンバ変数| |
| |_____| |
|        |
| | ̄ ̄ ̄ ̄ ̄| |
| |メソッド | |
| |_____| |
|________|

クラス直下のstaticを呼び出すときには、スコープ定義演算子 :: を使って呼び出します。呼び名はダブルコロンでもいいよ。

/**
 * テストクラス
 */
class test_class
{
  public static $test_static_hensu = 100;

  protected $test_menber_hensu;

  public function __construct()
  {
    # code...
  }

  public static function test_method($test_hikisu)
  {
    echo htmlspecialchars($test_hikisu, ENT_QUOTES);
  }
}

//クラスのインスタンス化
$instance = new test_class();

//staticメソッドの呼び出し
$instance::test_method('こんにちは');

//static変数の呼び出し
echo $instance::$test_static_hensu;

この時に、static変数の場合は$が付いていることに注意しよう。変数という意味で$を付けないとエラーになるよ。

それでこのダブルコロンでの呼び出しの場合は、インスタンス化しないで呼び出していることになるので、メモリの消費が少なくて済むというメリットがあります。

だけど直接呼べちゃうので、むやみやたらに設定すると、あちこちのクラスに設定値があることになり、管理がしずらくなるという危険性もあります。

staticの使いどころは難しいのだけれども、初心者のうちはほとんど使わないと思った方がいいかもしれないです。

使うとすれば、ユーティリティのような、その時だけ使うとか、ちょっとした道具みたいなものを関数化して、クラスにまとめているだけ、みたいな時には使えますね。

class date_henkan
{
    public function __construct()
    {
      # code...
    }

    public static function testEigoDate($time) {
        return date('Y-m-d H:i:s', $time);
    }

    public static function testJapanDate($time) {
        return date('Y年m月d日 H時i分', $time);
    }
}

echo date_henkan::testEigoDate(time())."<br>\n";

echo date_henkan::testJapanDate(time());
クラス内部からのstaticの呼び出し方

それと、大事なことにstaticの場合はthisは使えないということです。

もうほんと別物ですよね。別物なので何からなにまで違うのです。
そういうふうに丸暗記した方が早いです。

staticの場合は、self や parent を使用します。thisの代わりになるのがselfです。
子どもクラスから親クラスを指定する場合にはparentを使用します。

例えば、以下のようなテストクラスを作成して、3パターンの呼び出しをしてみます。

class testClass
{
    public static $static_hensu = 'Hello';

    public function __construct()
    {
      # code...
    }

    public function testMethod() {
        return self::$static_hensu;
    }
}

//1.クラス名を指定してstatic変数を呼ぶ
var_dump(testClass::$static_hensu);

//2.クラスをインスタンス化し、メソッド経由でstatic変数を呼ぶ(thisはエラーになるのでselfを使用する)
$instance = new testClass();
var_dump($instance->testMethod());

//3.static変数の呼び出し
var_dump($instance::$static_hensu);

1番目と3番目の呼び出しはダブルコロン :: を使用して、素直にstaticを呼び出しています。
3番目は、2番目でインスタンス化されているように見えますが、結局ダブルコロンで直接呼び出しています。

2番目ですが、これはクラスをインスタンス化していますね。
インスタンスとしてメソッドを呼び出しています。
そのメソッドの内部で、自分自身としてselfを使用し、static変数を呼び出しています。

今度はこのソースコードに子どもクラスを追加して、子どもクラスから呼び出してみましょう。

class testClass
{
    public static $static_hensu = 'Hello';

    public function __construct()
    {
      # code...
    }

    public function testMethod() {
        return self::$static_hensu;
    }
}

class kodomo extends testClass
{
    public function __construct()
    {
      # code...
    }

    public function testKodomoMethod() {
        return parent::$static_hensu;
    }
}

//1.親クラスを継承した子クラスからstatic変数を呼ぶ
var_dump(kodomo::$static_hensu);

//2.子クラスをインスタンス化し、子メソッド経由でstatic変数を呼ぶ(thisはエラーになることと、親のstatic変数なのでparentを使用する)
$kodomo_instance = new kodomo();
var_dump($kodomo_instance->testKodomoMethod());

testClassを親として継承し、kodomoクラスを作りました。

1番目の呼び出しは、継承したstatic変数を素直に呼び出しています。

2番目の呼び出しは、インスタンス化したkodomoクラスのメソッドから、親のstatic変数を呼び出しています。
親のstatic変数を呼び出すので、parentを使用しています。

まとめですが、

クラスをインスタンス化して、メンバ変数メソッドを呼び出す場合は、アロー演算子 ->で呼び出す、内部ではthisを使う。

staticというクラス直下に設定されたものは、static変数staticメソッドと呼び、ダブルコロン ::で呼び出す、内部ではselfparentを使うということです。

そして、この2つは別物ということです。

あと、static変数の初期化の挙動なのですが、初回だけ初期化されるというのが単純な言い方なんですが、詳しく検証してくれている方がいますので、そちらを参照してみてください↓
PHPの静的変数 (static変数) の挙動まとめ – Qiita

========================================

▼PHPのオブジェクト指向とデザインパターン記事一覧

関連記事

コメント

  • トラックバックは利用できません。

  • コメント (0)

  1. この記事へのコメントはありません。