phpでクラスの継承を利用しているとき、親クラスのstatic変数が子クラスでどう扱われるかというポイントで嵌ったので公開する。
理屈がわかってしまえば当たり前の動きなのだが、インスタンス変数の感覚でいたため痛い目にあってしまった。
継承関係にある次のクラスを作成する。
class A{
public static $a = 'a';
}
class B extends A{
public static function init(){
self::$a = 'b';
}
}
class C extends A{
public static function init(){
self::$a = 'c';
}
}
ここで次の処理はさすがに自明な結果を返す。
echo A::$a . "\n"; // > a
echo B::$a . "\n"; // > a
echo C::$a . "\n"; // > a
ここで次の魔法をかける。
B::init();
するとさきほどの結果は次のように変化する。
echo A::$a . "\n"; // > b
echo B::$a . "\n"; // > b
echo C::$a . "\n"; // > b
つまり、自身のstaticプロパティを書き換えたつもりでも、親も兄弟もすべて書き換えてしまったかのような結果となる。
上のように明確な定義をしていれば、まあなんでもない挙動だが、もともと親になかったstaticプロパティが
ある日突然親に追加された瞬間、地獄を見る。
ちなみに、class Bでstatic変数を再定義しておけば、上記のような現象は回避される。
class B extends A{
public static $a = 'a';
public static function init(){
self::$a = 'b';
}
}
B::init();
echo A::$a . "\n"; // > a
echo B::$a . "\n"; // > b
echo C::$a . "\n"; // > a