[PHP] static修飾子について

static修飾子を使った静的変数、静的プロパティ、静的メソッドについてです。

静的変数

関数内で定義された変数のスコープはローカルスコープと言い、呼び出し元のスコープや外部のスコープからは参照できず、関数が終了したら値ごと破棄されます。

しかし、変数を静的変数で定義することで、変数の値を関数終了後も値を維持しておくことが可能です。

定義

static 変数;

[実装例] 通常の変数定義

コード

以下のコードは通常の変数定義です。

function counter() {
    $var = 0;
    $var++;
    return $var;
}

$count = counter();
print "count={$count}\n";

$count = counter();
print "count={$count}\n";

$count = counter();
print "count={$count}\n";

実行結果

ローカル変数 $var の値は counter関数が終了するたび破棄されるので、何度呼び出しても結果は変わりません。

$ php test_static.php
count=1
count=1
count=1

[実装例] 静的変数での変数定義

コード

以下のコードは変数 $var を、静的変数で定義した例です。

function counter() {
    static $var = 0;
    $var++;
    return $var;
}

$count = counter();
print "count={$count}\n";

$count = counter();
print "count={$count}\n";

$count = counter();
print "count={$count}\n";

実行結果

$var の値はcounter関数の終了後も保持されているのが分かります。

$ php test_static.php
count=1
count=2
count=3

静的プロパティ

クラスのプロパティをstaticで修飾することで、静的プロパティとして定義することが出来ます。

静的プロパティはクラスのインスタンスを生成することなく、アクセスすることが可能です。

静的プロパティへのアクセス

クラス名::プロパティ名

[実装例] 静的プロパティへのアクセス

コード

class Test {
    static $var = 100;
}

print "var=" . Test::$var . "\n";
Test::$var += 50;
print "var=" . Test::$var . "\n";

実行結果

$ php test_static.php
var=100
var=150

[実装例] クラスのインスタンスから静的プロパティへのアクセス

クラスのインスタンスからも同じ方法(インスタンス::静的プロパティ)でアクセスすることが出来ます。

コード

class Test {
    static $var = 100;
}

$test = new Test();
print "var=" . $test::$var . "\n";

実行結果

$ php test_static.php
var=100

[間違った実装例] クラスのインスタンスから静的プロパティへのアクセス

通常の属性と同じようにアクセス(インスタンス->静的プロパティ)した場合はエラーが発生します。

コード

class Test {
    static $var = 100;
}

$test = new Test();
print "var=" . $test->var . "\n";

実行結果

$ php test_static.php
PHP Notice:  Accessing static property Test::$var as non static in .\test_static.php on line 35

Notice: Accessing static property Test::$var as non static in .\test_static.php on line 35
PHP Warning:  Undefined property: Test::$var in .\test_static.php on line 35

Warning: Undefined property: Test::$var in .\test_static.php on line 35
var=

[実装例] スーパークラスの静的プロパティへアクセス

スーパークラスの静的プロパティであっても、クラス名指定、またはインスタンスからアクセスすることが出来ます。

コード

class Test {
    static $var = 100;
}

class SubTest extends Test {
}

print "var=" . SubTest::$var . "\n";
SubTest::$var *= 2;

$test = new SubTest();
print "var=" . $test::$var . "\n";

実行結果

$ php test_static.php
var=100
var=200

静的メソッド

インスタンスを生成せずともクラス名から直接呼び出せるメソッドのことを静的メソッドと言います。

定義

static メソッド名() {
    //
}

[実装例] 静的メソッドを実行する

静的メソッドに関しても基本的に静的プロパティと同様に、クラス名を指定して呼び出すか、インスタンスから呼び出すことが可能です。

class Test {
    static function getVar() : int {
        return 100;
    }
}

// クラス名でstaticメソッドを実行
print "var=" . Test::getVar() . "\n";

// クラスのインスタンスからstaticメソッドを実行
$test = new Test();
print "var=" . $test::getVar() . "\n";

実行結果

$ php test_static.php
var=100
var=100

[実装例] 静的メソッドから静的プロパティを参照する

静的メソッド内の処理から、クラスの静的プロパティを参照する場合は、selfキーワード、またはstaticキーワードを使用します。

class Test {
    private static int $var = 100;

    static function getVar() : int {
        return self::$var;
    }
}

print "var=" . Test::getVar() . "\n";

実行結果

$ php test_static.php
var=100

[間違った実装例] 静的メソッドから静的プロパティを参照する

コード1

静的メソッドはインスタンスを持たないので $thisキーワードを使った参照はできません。

class Test {
    private static int $var = 100;

    static function getVar() : int {
        return $this->var;
    }
}

print "var=" . Test::getVar() . "\n";

コード2

以下のようにキーワードなしの場合もエラーになります。この場合は変数 $var をローカル変数として探しますが、未定義なのでエラーになります。

class Test {
    private static int $var = 100;

    static function getVar() : int {
        return $var;
    }
}

print "var=" . Test::getVar() . "\n";

コード3

staticメソッドからインスタンスのメンバ変数へアクセスることはできません。

class Test {
    private int $var = 100;

    static function getVar() : int {
        return self::$var;
    }
}

print "var=" . Test::getVar() . "\n";

コメント

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)