PHPオブジェクト指向基礎
静的メンバ
静的メンバとは
クラスのメンバへのアクセスはインスタンスを生成しなければ出来ませんでした。
しかしインスタンスを生成しなくてもアクセス可能なメンバも作れます。
これを「静的(スタティック)メンバ」と呼んでいます。
まずは例を見てください。
<?php class PriceFormater { public static function formatJapanese($price) { $price = number_format($price); $price = $price . '円'; return $price; } public static function formatBasic($price) { $price = number_format($price); $price = '\' . $price; return $price; } } $price = PriceFormatter::formatBasic(2000); echo $price; $price = PriceFormatter::formatJapanese(3000); echo $price; ?>
string(8) "\2,000" string(8) "3,000円"
普通のメソッドとは違い、「static」というキーワードが付いています。
これも修飾子の一つです。staticをつけたメソッドはインスタンスを生成しなくても直接「クラス名::メソッド名()」で呼び出します。
フィールドも同じです。
例えば「public static $aaa;」という感じで定義したフィールドは、
「クラス名::$フィールド名」で直接参照が可能です。
そしてもちろん、クラスの外より呼び出すわけですからアクセス修飾子は「public」の場合に限ります。
クラス内よりアクセスする場合は、
「self::$フィールド名」「self::メソッド名()」となります。
逆にstaticメソッドはインスタンスよりの呼び出しは出来ません。
静的メンバの考え方
通常のメンバはクラスインスタンスに属します。
なので同じクラスをもとにしていても、別々のインスタンスであれば保持する値はそれぞれ別々です。
メソッドもインスタンスに属するメソッドと考えます。メソッドは基本的にはフィールドに対するアクセサと考えることも出来ます。フィールドに値をセットする、フィールドの値を加工して返す、という感じです。
対して静的メンバはクラスそのものに属します。
そのためインスタンスメンバとは基本的に関わりがありません。
静的メンバとインスタンスメンバの間には一切関係がないのです。
分かりにくいかもしれませんが、要はフィールドの値に絡む処理であるかどうか、というところです。
別に絡まなくてもインスタンスのメソッドでも全然問題ないのですが、絡まないならstaticでもいい、ということです。
オブジェクト指向の最大の特徴はインスタンスの性質にあります。
なので、インスタンスの特性とは関係のない静的メソッドは、ほとんど関数と同じような扱いです。クラスのメソッドではなくて普通の関数ありますよね。
あれは引数を受け取って、加工して返す、という感じの役割を果たしていると思います。
まさにそんな感じのものです。
なので例えば計算処理クラスとか言うのを作ったとしたら、
メソッドは全部staticになるんじゃないでしょうか。
<?php class Calculator { // 足し算 public static function addition($int1, $int2) { return $int1 + $int2; } // 引き算 public static function substraction($int1, $int2) { return $int1 - $int2; } // 平均値を求める public static function getAverage($intVals) { if (false == is_array($intVals)) { return false; } $cnt = count($intVals); $total = 0; foreach ($intVals as $int) { $total += $int; } $average = $total / $cnt; return $average; } } $answer = Calculator::addition(10, 1); var_dump($answer); $answer = Calculator::substraction(10, 1); var_dump($answer); $intVals = array(1, 2, 3, 4, 5, 6, 7); $answer = Calculator::getAverage($intVals); var_dump($answer); ?>
int(11) int(9) int(4)
計算クラスっていうのはメソッドごとに受け取った引数の計算結果を返すという、処理がメソッドだけで完結するものです。つまり、フィールドを必要としません。
もちろん設計によりますが、こういったユーティリティ的なクラスは静的メソッドが多くなる傾向にあります。別にスタティックにしなくても出来ますが、スタティックの方が気軽に利用できます。インスタンスの生成とかしなくてもいいので。
あまり意味はないかもしれませんが、以下のようなクラスも考えられます。
<?php class String { // 文字列分割 public static function split($splitter, $string) { return explode($splitter, $string); } // 配列結合 public static function join($glue, $array) { if (false == is_array($array)) { throw new Exception("結合対象が配列ではありません"); } return implode($glue, $array); } // 文字切り出し public static function substring($string, $start, $length = null) { if (null == $length) { return substr($string, $start); } else { return substr($string, $start, $length); } } } ?>
「String」クラスと称して、文字列操作クラスを作成しました。
といっても、見たとおり各メソッドは、同じ動きをするPHPの標準関数を実行して結果を返しているだけです。
意味は薄いですが、関数を直接呼び出すってのはオブジェクト指向的ではないため、あえてクラスの中に関数を閉じ込めてみました。しかし、文字列操作の関数を集めてStringクラスを作っているので、文字列処理として関数をパッケージングしていることになります。
こういうクラスをラッパークラスなんて呼んだりします。
元々存在する、標準関数などの処理をクラスの中に包み込み(ラッピング)、より分かりやすく、より便利な形で提供するクラスです。
上の例は文字列操作系の関数をいくつかラッピングしていますが、単に標準関数を呼び出だすだけでは芸がないので、ある程度のチェックロジックを入れました。
まあ標準関数なんて無数にあるのでやりだしたらキリがないのでこういうことはあまりやりませんけどね。
静的メソッドの例としてみてください。

オーバーライド

