Code Fix

上級

staticを付け忘れると、インスタンス間でプロパティが共有されない

インスタンスをまたいで値を共有したい場合はstaticプロパティが必要です。staticを付け忘れると、そのプロパティは各インスタンスに独立して属するため、期待した共有ができません。

エラーメッセージの読み方

Fatal error: Uncaught Error: Access to undeclared static property Counter::$count in main.php:5
main.php
ファイル名
5
行番号 — 実際にクラッシュした行
Error
例外クラス — 何が起きたか。ここを検索するのが最短です
Access to undeclared static property Counter::$count
内容 — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  <?php
 2  class Counter {
 3      public          int $count = 0;
                   ^
 4      public function increment() {
 5          self::$count++;
 6      }
 7  }
 8  $a = new Counter();
 9  $b = new Counter();
10  $a->increment();
11  $a->increment();
12  $b->increment();
13  echo Counter::$count;
Fatal error: Uncaught Error: Access to undeclared static property Counter::$count in main.php:5

staticを付けずに宣言すると$countはインスタンスごとの通常のプロパティになります。それをself::$countという静的な書き方でアクセスしようとすると、静的プロパティとして宣言されていないため致命的エラーになります。

直し方: (空) を static にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  <?php
 2  class Registry {
 3      public          int $total = 0;
                   ^
 4      public function add($n) {
 5          self::$total += $n;
 6      }
 7  }
 8  $a = new Registry();
 9  $b = new Registry();
10  $a->add(10);
11  $b->add(5);
12  echo Registry::$total;
Fatal error: Uncaught Error: Access to undeclared static property Registry::$total in main.php:5

staticの無い$totalをself::$totalとして扱おうとすると、静的プロパティが宣言されていないため致命的エラーになります。全インスタンスで共有したい値にはstaticが必要です。

直し方: (空) を static にします。

この問題を解いてみる →

パターン3

 1  <?php
 2  class Logger {
 3      public          int $entries = 0;
                   ^
 4      public function log() {
 5          self::$entries++;
 6      }
 7  }
 8  $a = new Logger();
 9  $b = new Logger();
10  $a->log();
11  $b->log();
12  $b->log();
13  echo Logger::$entries;
Fatal error: Uncaught Error: Access to undeclared static property Logger::$entries in main.php:5

$entriesにstaticが無いままself::$entriesとしてアクセスすると、静的プロパティとして宣言されていないため致命的エラーになります。

直し方: (空) を static にします。

この問題を解いてみる →

パターン4

 1  <?php
 2  class Cache {
 3      public          int $hits = 0;
                   ^
 4      public function hit() {
 5          self::$hits++;
 6      }
 7  }
 8  $a = new Cache();
 9  $b = new Cache();
10  $a->hit();
11  $b->hit();
12  $b->hit();
13  echo Cache::$hits;
Fatal error: Uncaught Error: Access to undeclared static property Cache::$hits in main.php:5

staticを付けずに宣言すると$hitsはインスタンスごとの通常のプロパティになります。それをself::$hitsという静的な書き方でアクセスしようとすると致命的エラーになります。

直し方: (空) を static にします。

この問題を解いてみる →

パターン5

 1  <?php
 2  class Pool {
 3      public          int $used = 0;
                   ^
 4      public function consume() {
 5          self::$used++;
 6      }
 7  }
 8  $a = new Pool();
 9  $b = new Pool();
10  $a->consume();
11  $a->consume();
12  $b->consume();
13  echo Pool::$used;
Fatal error: Uncaught Error: Access to undeclared static property Pool::$used in main.php:5

$usedにstaticが無いままself::$usedとしてアクセスすると、静的プロパティとして宣言されていないため致命的エラーになります。

直し方: (空) を static にします。

この問題を解いてみる →

よくある誤解

「クラスに書いたプロパティはクラス全体で1つのはず」という思い込みは誤りです。staticを付けない限り、プロパティはnewするたびに新しく作られる、インスタンスごとに独立した値になります。

実務での勘所

静的プロパティは、明示的に子クラス側で再宣言しない限り、親クラスと全ての子クラスで同じ1つの実体を共有します。ParentClassでstaticなカウンタを宣言し、ChildAとChildBがそれを継承してそれぞれ操作すると、実は同じ1つの値を奪い合っていることになります。サブクラスごとに独立したカウンタが欲しい場合は、それぞれの子クラスで同名のstaticプロパティを再宣言する必要があり、そうして初めてそのサブクラス系統専用の別の実体として扱われます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)