今では普通に使っているけど
Laravelを使い始めた頃、staticなクラスメソッドをコールすることに少し違和感があった。
一応、言語仕様に従って正しく動作するプログラムは書けるけど
staticなクラスメソッドとはどういうものかが未だに分からない(笑)
■staticとは?
まず、static変数について考えてみようと思う。
static変数とは、あるメモリに固定配置され
外部変数のようだがコンパイルで変数のスコープが制限される。
そして、クラスメソッドのstaticについて考えると
staticメソッドの場合は、あるメモリに展開された(クラスの原本の)メソッドをコールし
staticではないメソッドの場合は、クラスの原本からコピー(インスタンス化)されたメソッドがコールされる。
多分、この方が「なるほど!!」って理解しやすいから
こういう説明をする人が多いんじゃないかと思う。
別に細かいことを言うつもりはなくて
概念と使い方、結果が一致していれば問題ないと思います。
しかし、「クラスメソッドのstaticとは何なのか?」というような疑問が浮かぶとついつい深みにハマっていく。
■さらに深掘ってみる ※僕の考え
変数の場合は、staticをつけるとコンパイルであるメモリに割り当てられ
staticなしの場合は、インスタンス化で変数領域がコピー(実際にはスタックに積まれる??)される。
※PHPの場合、あるメソッドの中でオブジェクトを生成してそのオブジェクトをコール元に返すことが出来るのでスタックではないかも。。。
だけど、メソッドの場合は、staticつけようがインスタンス化されようと
コードの実態は1つだと思うんですよ!!
つまり、プログラムカウンタが指し示すのはどちらも同じで変数の参照先が違うだけ。
こんなこと書いておいて、PHPのソースコードを解析した訳ではないので間違ってるかもしれないけど。。。
結局、staticなクラスメソッドは、newせずに’->’ではなく’::’でコールするってくらいしか違いが分からない。
どういう使い分けやメリットがあるのだろう??
よく分からないから最後に正しいコーディングの仕方と動作結果をまとめてみる。
■staticなクラスメソッド、変数のまとめ
1.変数もメソッドもstaticなしの場合
class func{
private $val;
public function set($val){
$this->val = $val;
}
}
コール元
$func = new func();
$func->set('Hello');
よく使われるやつ
インスタンスごとにvalは独立する
2.変数がstatic、メソッドはstaticなしの場合
class func{
private static $val;
public function set($val){
self::$val = $val; // thisではなくselfになる
}
}
コール元
$func = new func();
$func->set('Hello');
※コール元は、ケース1と同じ
インスタンスを複数生成しても、valの値は共有される
3.変数はstaticなし、メソッドがstaticの場合
class func{
private $val;
public static function set($val){
プライベート変数valにはアクセス出来ない
$this->valもself::$valもエラーとなる
}
}
コール先のメソッドがstaticなプライベート変数にアクセスしなければ正常処理される。
例えば、+2した値を返すaddメソッドの場合は
$ret = fnc::add(4);
の戻り値は6でエラーとならないが、実際はこんな使い方はしない。
4.変数もメソッドもstaticありの場合
class func{
private static $val;
public static function set($val){
}
}
コール元
$ret = fnc::set('Hello');
2とは、コールの仕方以外に違いがあるのかな??
ローカル変数のstaticまで検証しないと2と4の違いが分からないのかな??
う~ん、結局staticなクラスメソッドってなんなんだ!!
もう疲れたから終わり!