PHP入門 | 構造化とオブジェクト指向 | クラスメソッドとクラスフィールド

これまでは「クラスはインスタンスを作って操作する」ことが基本だと説明してきた。しかし、実は必ずそうしなければならないわけではない。クラスをクラスのまま使うこともできる。ただし、そのためにはメソッドやフィールドを別の形で書く必要がある。

インスタンスではなく、クラスから直接使えるメソッドやフィールドを「クラスメソッド」「クラスフィールド」と呼ぶ。クラスを単なる設計図と考えると、どうしてクラスの中に値を保存したりメソッドを実行したりできるのか少し不思議に感じるが、「クラスもオブジェクトであり、クラスというオブジェクトをもとにインスタンスというオブジェクトを作っている」と想像するとよい。

クラスで提供するメソッドやフィールドには、前にstaticというキーワードを付ける。これは「静的」という意味で、クラスメソッドやクラスフィールドは「staticメソッド」「staticフィールド」とも呼ばれる。

それでは、この基本的な使い方を簡単にまとめてみよう。定義は次のように書く。

static $変数;
static function メソッド(仮引数) {...}

このように前にstaticを付けるだけでよい。アクセスキーワードを入れる場合は、static private $hoge;のようにstaticの後に書く。これらのフィールドやメソッドの呼び出しは次のように書く。

クラス::$変数;
クラス::メソッド(引数);

クラス名の後に::という記号を付けて書く。注意すべきなのはフィールドである。インスタンスフィールドはクラス->変数のように書くが、クラスフィールドの場合はクラス::$変数のように、$を付けて書く。

これも実際の例を見てみよう。

<?php
class TextModify {
    static private $header = "<b>";
    static private $footer = "</b>";
    static private $find = "PHP";
     
    static function setTagData($h,$f) {
        self::$header = $h;
        self::$footer = $f;
    }
     
    static function setFind($f) {
        self::$find = $f;
    }
     
    static function writeRenderText($s) {
        $res = str_replace(self::$find, self::$header . self::$find . self::$footer, $s);
        echo $res;
    }
}
     
// クラスを準備
TextModify::setTagData('<span style="font-size:200%;">', '</span>');
TextModify::setFInd('PHP');
 
if ($_POST != null){
    $str = $_POST['text1'];
}
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>
        <?php
        TextModify::writeRenderText('Hello PHP!');
        ?>
        </h1>
        <p><?php TextModify::writeRenderText('ここにPHPという文字を含む文章を書いてください。'); ?></p>
        <hr>
        <p><?php TextModify::writeRenderText($str); ?></p>
        <form method="post" action="./index.php">
            <textarea name="text1" cols="40" rows="5"><?php echo $str; ?></textarea>
            <br><input type="submit">
        </form>
        <hr>
    </body>
</html>

上の例は、以前のTextModifyクラスを、クラスメソッドとクラスフィールドを利用する形に書き直したものである。ここではPHPというテキストを2倍のフォントサイズで表示している。

この例では、setTagDataで挟み込む前後のタグを設定し、setFindで検索文字を設定する。

TextModify::setTagData('<span style="font-size:200%;">', '</span>');
TextModify::setFInd('PHP');

newでインスタンスを作ることなく、直接クラスに値を設定している。そしてテキストを出力するときは、次のようにそのままメソッドを呼び出すだけである。

TextModify::writeRenderText('Hello PHP!');

非常に簡単に使えている。

クラスメソッドとクラスフィールドを使うと、インスタンスを作らなくてもこのように簡単に機能を呼び出せる。一方で、さまざまなデータを保持し、それに応じて動作する場合は、使うたびに多くのデータを設定し直さなければならないため、とても複雑になる。

多くのデータを保持し、それに従って処理を行うものは、インスタンスを作って使うほうがはるかに便利である。クラスメソッドは、変更することがほとんどないデータしかない場合や、単に決まった機能を呼び出すだけの場合に使うとよい。

たとえば、数値計算、つまり引数として数値を渡して結果を返してもらう処理などをクラスにまとめて使う場合は、毎回インスタンスを作るより、クラスメソッドとして手軽に呼び出すほうが便利である。用途に応じて使い分けるとよい。