LoginSignup
12
14

More than 3 years have passed since last update.

staticをインスタンス化した後から指定するとどうなるか

Last updated at Posted at 2021-03-27

はじめに

最近、staticがインスタンス化したものにも影響を及ぼすということを知らずに使ってしまい、その挙動に戸惑ったことがあるのでそのことについて書きたいと思います。
この記事を読めばstaticの理解が少し深まります。

まず、以下のような課題があったとします。

Q. 以下の仕様を満たし、次の出力結果が出るようにコードを追記せよ。※環境はPHP7.4とします。

出力結果

田中さんは日本人です。
ジュリーさんはアメリカ人です。
黄さんは中国人です。
ミュラーさんはドイツ人です。
<?php

class Person
{
    /* コードを記述 */
}

$person1 = new Person("田中", "日本");
$person2 = new Person("ジュリー","アメリカ");
$person3 = new Person("黄","中国");
$person4 = new Person("ミュラー","ドイツ");

$persons = [ $person1, $person2, $person3, $person4 ];
foreach ($persons as $person) {
    echo /* コードを記述 */ . "さんは" . /* コードを記述 */ . "人です。\n";
}

さて皆さんは無事に書けましたかね
コード例は以下になります。

<?php

class Person
{
    public $name;
    public $country;

    public function __construct($name,$country) {
        $this->name = $name;
        $this->country = $country;
    }
}

$person1 = new Person("田中", "日本");
$person2 = new Person("ジュリー","アメリカ");
$person3 = new Person("黄","中国");
$person4 = new Person("ミュラー","ドイツ");

$persons = [ $person1, $person2, $person3, $person4 ];
foreach ($persons as $person) {
    echo $person->name . "さんは" . $person->country . "人です。\n";
}
田中さんは日本人です。
ジュリーさんはアメリカ人です。
黄さんは中国人です。
ミュラーさんはドイツ人です。

本来はこれで問題ないのですが、当初私は、スコープ演算子を使って、どこからでもアクセスができるstaticを使うのもいいんじゃない?いけるんじゃね?と考えた結果、以下のようにコードを考えました。

<?php

class Person
{
    public static $name;
    public static $country;

    public function __construct($name,$country) {
        self::$name = $name;
        self::$country = $country;
    }
}

$person1 = new Person("田中", "日本");
$person2 = new Person("ジュリー","アメリカ");
$person3 = new Person("黄","中国");
$person4 = new Person("ミュラー","ドイツ");

$persons = [ $person1, $person2, $person3, $person4 ];
foreach ($persons as $person) {
    echo Person::$name . "さんは" . Person::$country . "人です。\n";
}

すると
出力結果は

ミュラーさんはドイツ人です。
ミュラーさんはドイツ人です。
ミュラーさんはドイツ人です。
ミュラーさんはドイツ人です。

となり、あれ?ミュラーさんが4人も出てきたぞ!なんでやねんおかしいやろ!?
ってことで知人エンジニアに質問をしたり調べたりでこうなる理由が解明できました。

要はstatic変数はクラスレベルの変数のため、static変数を変更すると、そのクラスのすべてのインスタンスに影響するとのことです。

以下の記事のなぜstaticを乱用してはいけないのかが特に参考になりました。
https://qiita.com/ue_knnk/items/fa84b8bc30ba319e5744

なので今回のコードに関しては、コンストラクタで、$name$countryを代入してそれらがstatic変数になるという仕組みになってしまった結果、
一番最後に代入されたミュラードイツがstatic変数となってしまい既にインスタンス化された他の3つにも影響し、このような出力結果になってしまったという訳です。(なるほど)

最後に

今回はstaticについての記載をしましたが、私を含めこれを知らなかった初学者もいると思いますので(いなかったらすみません)少しでも役立って貰えれば幸いです。

12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14