anybody's game

日々感じたこと、艦隊これくしょん、千年戦争アイギス、読書記録

ゲッタとセッタ・・・なんでこんな面倒なことするの?

<?php 

// PHPの解説本なんかで、
// ゲッタとセッタの実装方法は
// だいたいこんな風になっている。

class Add {
    protected $x;
    public function setX($value)
    {
        $this->x = $value;
    }
    public function setY($value)
    {
        $this->y = $value;
    }
    public function getX()
    {
        return $this->x;
    }
    public function getY()
    {
        return $this->y;
    }
    protected $y;

    public function execute()
    {
        echo $this->x + $this->y  . '<br />';
    }
}

$Add = new Add();
$Add->setX(10);
$Add->setY(3);
$Add->execute();



// しかし、これで何の役に立つのか?
// っていまいちピンと来ないかもしれない。
// カプセル化は重要だけど、PHPには
// もともとファンクションブロックの
// スコープがあるから、クラス化したからってどうということはない。
// なので、役にたちそうだなって思えそうなTipsを書いておきます。

class Add2 {

    protected $x;
    protected $y;
    const DEFAULT_X = 10;

    // セッタメソッドがあれば、値のチェックができる。
    // セッタから何かしらの値が返ってくるように
    // しておけば、エラーチェックの代わりにもなる。

    public function setX($value)
    {
        if (is_numeric($value)) {
            $this->x = $value;
            return $this->x;
        } else {
            trigger_error('setXメソッドの実行に失敗しました。', 
                E_USER_WARNING);
        }
    }

    // セットに失敗したとき、とりあえず、
    // メッセージとともに、デフォルト値を返してもよいかも。
    public function setY($value)
    {
        if (is_numeric($value)) {
            $this->y = $value;
            return $this->y;
        } else {
            echo 'setYメソッドの実行に失敗しました。';
            return $this->getY();
        }
    }

    // ゲッタメソッドでやれること
    // 変数に値がセットされていなかったとき、
    // 別のソース(DB,定数等)から
    // デフォルト値をとってくることができる。
    // クラス内定数・DB・・・etc

    public function getX()
    {
        if (!isset($this->x)) {
            $this->x = self::DEFAULT_X;
        }
        return $this->x;
    }
    public function getY()
    {
        if (!isset($this->y)) {
            $this->y = $this->getDefaultY();
        }
        return $this->y;
    }

    public function getDefaultY()
    {
        // ここは、たとえば、外部クラスとか、
        // DBへのリソースとか柔軟に変わる感じならより
        // 柔軟性アップ

        return 5;
    }

    public function execute($args = array())
    {

        // セッタでセットに成功したとき
        // そのまま引数を返すようにしておけば、
        // こういうこともできる。
        // ゲッタから何かしらの値が返ってくるように
        // しておけば、エラーチェックの手間も省ける。

        if (isset($args['x'])) {
            $x = $this->setX($args['x']);
        } else {
            $x = $this->getX();
        }

        // 最終的な処理の際、引数の数を柔軟にできる。
        // こうすれば、引数のYが優先するが、
        // セットされていなかった場合、デフォルト、
        // もしくは設定されていた値を用いることができる。

        if (isset($args['y']) OR !is_numeric($args['y'])) {
            $y = $this->getY();
        } else {
            $y = $args['y'];
        }


        echo $x + $y . '<br />';
    }

}

$Add = new Add2();
$Add->execute(array('x' => 10, 'y' => 10));    
// デフォルト値同士が足されて、20が出力
;
$Add->execute(); 
// Xは、実行時にセッタが呼ばれているので、10が、
// Yは、実行時にセッタが呼ばれていないので5が入っている。
// よって、15が出力される。

?>

まとめ

  • セッタとゲッタは、カプセル化以外にも役立つ場面が多い。
  • たとえば、セットするときにバリデーターとして。
  • セットされていない値をゲットされたときに振る舞いを指定できる。
  • たとえば、デフォルト値を返す、エラー、例外を返す・・・
  • 最終的な結果を出力するとき、引数を指定する方法とプロパティに設定する方法、2種類を簡単に提供できる。