◆staticでないメソッドのstatic変数はインスタンス間で共有されてる

いきなり結果です
------------------------------------- 普通なメンバ変数:$aのをインクリ a NORMAL_VAR : 1 b NORMAL_VAR : 0 $aだけ変わってる ------------------------------------- staticなメンバ変数はアクセス方法がインスタンス経由じゃない ------------------------------------- 普通なメソッドのstatic変数:$aと$bのをインクリ a NORMAL_METHOD : 0 a NORMAL_METHOD : 1 a NORMAL_METHOD : 2 b NORMAL_METHOD : 3 b NORMAL_METHOD : 4 b NORMAL_METHOD : 5 両方とも変わってる ------------------------------------- staticなメソッドのstatic変数:$aと$bのをインクリ a STATIC_METHOD : 0 a STATIC_METHOD : 1 a STATIC_METHOD : 2 b STATIC_METHOD : 3 b STATIC_METHOD : 4 b STATIC_METHOD : 5 両方とも変わってる

普通にメンバ変数とstaticメンバ変数

まず本当にただのメンバ変数
もちろん変更したところだけ変わります

次にstaticメンバ変数
これはアクセス方法が 「クラス名::$var;」とか「self::$var;」などインスタンス依存していないのでインスタンスのものを変えるという考え方ができません
$a->var;」と書くと警告かエラーが出ました

メソッド内のstatic変数

ここからがメインです

staticでないメソッドのstatic変数

普通(staticでない)メソッドを用意してその中にstatic変数を作ります
インスタンスごとにstatic変数が変わるとメソッドもメンバ変数と同じくインスタンスの数だけ作られている(メモリ上に確保)と考えられます
逆に static変数がインスタンス間で共有されていなければメソッドは1クラスで1つだけで$thisがついたときだけアクセスする先が違うと考えられます

ところでJavaScriptでは
this->a = function(){}」のようにするとインスタンスごとにメモリが確保されて無駄なので 「(constructor).prototype.a = function(){}」のようにconstructorになる関数のprototypeのプロパティに書くことで 1つのメソッドのメモリ確保するのはconstructorに付き1つで済むようにできます

結果は……

全部変わってます


インスタンスいっぱい作ってもメンバ変数分しかメモリは必要ないようです
PHPはzvalとかで変数管理してるので実際のバイト数と考えれば違うと思いますがメソッド分は確保してないと思われます

いいことだなー と思いはするのですが これ 意外と不便なこともありそうな気がします
クラス内で共有じゃなくてインスタンスごとに共有する変数が欲しいときだってあります

staticメソッドのstatic変数

最後のstaticメソッド内でstaticなメンバ変数を作ったとき
これはクラス内で1つのメソッドなのでそれのstatic変数なんだから全部のインスタンス共有です
staticでないメソッドのstaticメンバ変数と同じ動きになります

まとめると

static×staticがクラス共有
normal×staticがインスタンス共有
にしてほしかったです
だってこの2つが一緒なら下側いらないし


一応コードです↓
<?php class test{ public $normal_var = 0; public static $static_var = 0; public function normal_test($i){ static $static_var = 0; echoln($i . " NORMAL_METHOD : " . $static_var++); } public static function static_test($i){ static $static_var = 0; echoln($i . " STATIC_METHOD : " . $static_var++); } public function print_var($i){ echoln($i . " NORMAL_VAR : " . $this->normal_var); } } function echoln($m){ echo $m, PHP_EOL; } $a = new test; $b = new test; echoln("-------------------------------------"); echoln('普通なメンバ変数:$aのをインクリ'); $a->normal_var++; $a->print_var("a"); $b->print_var("b"); echoln('$aだけ変わってる'); echoln("-------------------------------------"); echoln('staticなメンバ変数はアクセス方法がインスタンス経由じゃない'); echoln("-------------------------------------"); echoln('普通なメソッドのstatic変数:$aと$bのをインクリ'); $a->normal_test("a"); $a->normal_test("a"); $a->normal_test("a"); $b->normal_test("b"); $b->normal_test("b"); $b->normal_test("b"); echoln("両方とも変わってる"); echoln("-------------------------------------"); echoln('staticなメソッドのstatic変数:$aと$bのをインクリ'); $a->static_test("a"); $a->static_test("a"); $a->static_test("a"); $b->static_test("b"); $b->static_test("b"); $b->static_test("b"); echoln("両方とも変わってる");


おまけ

こうすればインスタンス間でのみ共有なstatic変数が作れる
<?php class test{ public $t; public function __construct(){ $this->t = function($i){ static $static_var = 0; echo $i, " ", $static_var++, PHP_EOL; }; } } $a = new test; $b = new test; $x = $a->t; $x("a"); $x("a"); $x("a"); $x = $a->t; $x("a"); $x("a"); $x("a"); $y = $b->t; $y("b"); $y("b"); $y("b"); $y = $b->t; $y("b"); $y("b"); $y("b");
結果
a 0
a 1
a 2
a 3
a 4
a 5
b 0
b 1
b 2
b 3
b 4
b 5

わざわざ$x$yに入れているのは PHPがメンバ変数に関数入れた時に直接実行できないからです

そのまま値を返す関数を書いて
function _($x){
    return $x;

_($a->t)();
でいける みたいなのをどこかで見ましたが動きませんでした
そんなわけで一旦変数入ってます