yano3nora
7/2/2017 - 11:46 AM

[php: oop note] OOP in php note. #php

[php: OOP on PHP] Object Oriented Programming on PHP. #php

OOP 入門

なにか

OOP の概念と歴史

ソフトウェアを効率的にプログラミングするための仕組み・考え方・概念。また、その概念をプログラミング上で実装できるようにした言語の機能のことを指す。

先に PHP の基本をおさらい

OOP 基本 3 大要素

http://qiita.com/ritukiii/items/a1979c3bcdcea9454d53

  • カプセル化:クラスに依存を閉じ込める
  • 継承:処理を抽象化する
  • ポリモーフィズム:メソッド呼出をメッセージングで行う

で、何がうれしくなるのか

一言にいうと、変更に強くなる。

OOP をこれから学ぶ

http://qiita.com/mpyw/items/41230bec5c02142ae691

大前提として、「オブジェクト指向で書くこと」は一つの手段であり、全てのケースでベストプラクティスとは言い切れない。しかし「オブジェクト指向で書かれた "なにか" ( FW とかライブラリとか ) を使って機能実装する」機会はとても多いので まずは書いてあることが解る 状態にしておくべき。書いてあることが分かるようになったなら、次はそれを利用して自身の問題を解決できる。


基礎知識

クラスの基本形

// クラスの定義
class Human {  
  
  // クラスのプロパティの宣言
  private $name;
  private $age = 15;
  
  // クラスのコンストラクタ (初期化処理) の定義
  public function __construct($name='John') {
    $this->name = $name;
  }

  // Public なメソッドの定義
  public function sayHello($destName){
    echo 'Hello, '.$destName.'.'.PHP_EOL;
    echo 'My name is '.$this->name.'.'.PHP_EOL;
    echo 'I\'m '.$this->age.' years old.'.PHP_EOL;
  }
  
  // Private なメソッドの定義
  public function setAge($age) {
    return $this->age = $age;
  }
  
}

// クラスからオブジェクト (インスタンス) 生成
$HumanBob = new Human('Bob');

// オブジェクトのメソッドを実行
$HumanBob->setAge(29);
$HumanBob->sayHello('Charlie');  // Hello, Charlie. My name is Bob. I'm 29 years old.

// 親クラスを継承した子クラスの定義
class Child extends Human {}

オブジェクトの定義

PHP のデータ構造体 ( = Object ) の型定義には以下のような種類がある。

class hoge { クラス定義 }
class fuga extends hoge { hoge クラス継承の fuga クラス定義 }

// クラスのほかに、似たようなオブジェクト定義が色々ある
abstract foo { 抽象クラス定義 }
interface bar { インターフェイス定義 }
trait hoge { トレイト定義 } 

プロパティ

クラス内変数、メンバー変数とも。

private $foo = 'value';

メソッド

クラス内の関数。

public function bar($str) {
  echo $str;
}

アクセス修飾子

プロパティ・メソッドの「外部クラスからのアクセス制御」について制御するやつ。

修飾子アクセス制御
private自クラス内のみ許可
protected自クラスと継承先のみ許可
public外部クラスからのアクセス許可
class hoge {
    public    $bar      // 外部アクセス可
    private   $foo      // 外部アクセス不可
    protected $baz      // 継承先でのみアクセス可
    static    $val      // インスタンス化せずともアクセス可 & $this-> では呼べない
    /**
     * 上記 static $val は PHP の関数内等で利用される static $val = 0; などの「静的変数」扱いらしい
     * 
     * Ref) 静的変数?
     * - 関数・ブロック内で宣言しブロック終了後も値を保持する変数
     * - 宣言時リテラル( [ static $val = 0; ] 等=計算式でない記述 )で初期化処理可能
     * - 初期化処理移行呼び出されても初期化処理をスルーする仕様
     */
}

アロー演算子

インスタンス ( オブジェクト ) のプロパティやメソッドにアクセスするやつ。連想配列で扱うファットアロー => とは別物。

$obj->property;
$obj->method('arg');

new / インスタンス

クラス定義を参照して new 演算子や clone 演算子で生成したオブジェクトのこと。

$obj1 = new hoge();  // new演算子必須
$obj2 = new hoge();  // id別インスタンス扱い

// オブジェクトのコピーで扱う clone 
$obj3 = clone $obj1;

$this / 擬似変数

クラス内で、自クラスを参照するための組込み変数。

class Human {
  public $name = 'John';
  public function sayHello() {
    echo 'Hello, my name is '.$this->name.'!!';  // 自身の $name プロパティを参照
  }
}

$Human = new Human();
$Human->sayHello();   // Hello, my name is John!!

スコープ定義演算子 ( :: )

「::の左辺にあるメソッドやプロパティ名が右辺のスコープに属するよ」と明示する演算子で、下記の機能を有する。

  • 自クラスか親クラスの【プロパティ/メソッド】にアクセスする
  • あるクラスの【staticプロパティ/staticメソッド/定数】にアクセスする
記法スコープ使える場所
self::記述された自クラスを参照クラス定義の中でのみ使える
parent::記述された自クラスの親クラスを参照クラス定義の中で使える
クラス名::記述で明示したクラス名を参照クラス定義の外or中で使える
static::直近の非転送(self等でないクラス名を明示した)コールがあるクラスクラス定義の中

参考

名前空間 ( use / namespace )

PHP5.3より、冗長な命名規則を使って名前衝突を避けなくても良いように【名前空間】が実装された。(オブジェクトと関係ないけどオブジェクト指向を採用するような規模の開発で用いられるので一応...)

/* 
例えば以下のようなディレクトリ構成で開発するとき、同名クラス・関数・変数を使わないように...なんてチーム開発ではほぼ不可能である

/app
    /src
        /controller
        /model
        /view
    /vender
        /controller
        /model
        /view
        
そんな時に各衝突を避けてため、各ディレクトリに倣った名前空間を仮想的に作る
で、全ソースコードの先頭で「このファイルで扱うクラス名・関数名・変数名は~~名前空間でのみ有効だよ」というのを宣言する
*/

// バックスラッシュ区切りで空間を区切る
namespace App\Src\Controller;

/*
また、別の名前空間にアクセスしたいときは use 文を使う。これを使うことで自ファイル・自名前空間内に同一名称のクラスや変数がないとき、 use 先の名前空間を探索するようになる
*/
namespace App\Src\Controller;

use Vendor\HogeHogeLibrary;
use Vendor\PiyoPiyoUtility;

アクセサー ( setter / getter )

Setter

public / protected なメソッドを通して private プロパティに値を入れるような処理やそのメソッドのこと。setProperty(){}

Getter

public / protected なメソッドを通して private なプロパティを取得するような処理やそのメソッドのこと。getProperty(){}

カプセル化・モジュール化

オブジェクト指向の基本的な設計思想 自クラス外部クラス問わず全てのプロパティへのアクセスで上記アクセサーを経由することでバリデーションや入出力の処理を一元化でき、結果的にオブジェクト間のデータのやりとりを疎結合な状態にするもの。

  • モジュール→交換可能な構成要素
  • カプセル→疎結合かつ隠蔽されたロジック

初期処理・終了処理

コンストラクタ

インスタンス化された時自動的に走るクラスの初期化処理。エラー時はエラーをreturn出来ないのでtrycatchで例外を投げたりする。

  public function __construct() {
    echo "run constructor\n";
  }

デストラクタ

インスタンスされたオブジェクトにnullを入れたり、変数スコープが外れたり、プログラムが終了した時に自動的に走るクラスの終了処理。リソース解放とかに使う。

  public function __destruct() {
    echo "run destructor\n";
  }

イミュータブルなオブジェクト

不変的オブジェクト。セッターを用意せず、コンストラクタのみ値の代入を許可する設計のクラス。インスタンス時に値が入り以降は代入不可能なため、中身が明示的。

クラスの継承 ( レイヤー/レイヤリング )

// 継承先hogehogeには継承元hogeのプロパティ・メソッドが全て引き継がれる。
// 継承の重なりをレイヤー・レイヤリングなどと呼ぶ。
class hogehoge extends hoge {}

オーバーライド

継承先で継承元と同名のプロパティ・メソッドを宣言した時、継承先が優先され継承元を上書きすることになる。

継承先でのアクセス権

継承元プロパティ・変数が...

  • public→アクセスok
  • protected→アクセスok
  • private→アクセスng privateのオーバーライドは同名プロパティ・メソッドが2つ生まれてしまい致命的なバグを生むのでやらないこと。

継承先でのコンストラクタ・デストラクタ

言語によっては、クラス継承先で継承元のコンストラクタとデストラクタは自動的に呼び出されるが、PHPでは自動的に呼び出されない。
また、継承元のコンストラクタと継承先のコンストラクタを2重で実行したい時などオーバーライドされ継承元のコンストラクタが呼ばれなくなるという問題がある。

上記のような理由から、継承先で継承元のコンストラクタ・デストラクタ処理を呼び出すために、以下の記法で親クラスメソッドの実行をかけてあげる必要がある。

// 親クラスメソッドの呼び出し
parent::メソッド名();

class hogehoge extends hoge{
    public function __construct() {
        parent::__construct(); // 継承元クラスのコンストラクターを呼ぶ・処理の最初に書くこと
        echo "run hogehoge constructor\n";
    }
    public function __destruct() {
        echo "run hogehoge destructor\n";
        parent::__destruct(); // 継承元クラスのデストラクターを呼ぶ・処理の最後に書くこと
    }
}

これで継承元クラスhogeに実装したコンストラクタ・デストラクタと、継承先のコンストラクタ・デストラクタの両方が実行される。この [ parent::method() ] はコンストラクタに限らずどのメソッドでも使える。

マジックメソッド

Fatalエラーしたり、致命的なバグを生みそうなクラスへのアクセスに対する防御(例外投げて処理をエラー停止させないようにとか)手段で用いる。PHPにはコンパイルエラーがなく、動的型付けなので予期せぬアクセスに弱い。それを補うための実装をする時に使う。
具体的には、コンストラクタ・デストラクタなどの__から始まる「PHPが用意した、特定タイミングで自動的に呼び出される」メソッドのことを指す。

__set(){ } 
__get(){ }

↑はアクセス不能なプロパティの値を取る・値を入れるような動作をする時に暗黙的に実行されているメソッド。このマジックメソッドに(実行されたら即例外を投げる)みたいな処理を書けば、クラスのprivateプロパティを守ったり、存在しないプロパティへアクセスして(PHPの仕様通りに)新たに変数を生成したりせずに済む。

__call(){ }
__callStatic(){ }
__invoke() { }

↑はアクセス不能なクラスメソッドへのアクセスタイミングで呼ばれる。上記のメソッド版。インスタンスからの呼び出し( $obj->method(); )では _callが、外部からの静的呼び出し ( class::method(); )では _callStaticが呼ばれる。例外投げ( throw new Exception('エラー') )以外にも開発序盤のテスト用疑似アクセサーに使ったりもするらしい。
_invokeは無名関数を実行する際に暗黙的に呼ばれるマジックメソッド。インスタンス生成→インスタンスを無名関数的に実行しようとした時、エラーが出たら例外投げる的な使い方をする。

class hoge {
    public function __invoke() {
        echo "call method\n";
    }
}
$obj = new hoge();
$obj();

この他にインスタンスを文字列のように扱おうとした時に呼ばれる __toString() もある。

インターフェース

クラスより抽象度の高い「持つべきメソッドの宣言だけをする」構造体定義。
publicメソッドの宣言のみ記述でき、継承先のクラスに対して「このような機能を実装するべきである」ことを強く明示すると共に「継承先ではこれらメソッドが存在することを保証します」と明示する役割がある。
メソッドの実装はそのインターフェースの実装版(implement)として子クラスで定義する。PHPでは単一継承(子クラスは複数の親クラスを持てない)だが、インターフェースは多重継承可能(宣言だけをしているのでメソッドなどの名前衝突エラーが起きづらい為)

抽象クラスと抽象メソッド

抽象クラス

[ abstract class ~~ {} ]で定義する、クラス基本形の他に抽象メソッドを所有できる抽象度の高い上位レイヤクラス。継承は通常のクラスと同様extendsで行う。

抽象メソッド

上記抽象クラス内において、publicかprotectedで宣言し、「継承先ではこのようなメソッドを必ず実装せよ」という暗示と同時に、上位レイヤで実装できる箇所は実装し継承させられるメソッド。

抽象化と多重継承

PythonやCのように多重継承ができない言語(JavaやPHPやRuby)では、上記2つの上位レイヤクラスを使い、以下のようにクラスのレイヤー設計(レイヤリングアーキテクチャ)を行う。※C等の多重継承は便利な反面複雑になり易い、らしい。

  • クラスの"型"概念をインターフェースで暗示/保証
  • クラスの"実装"概念を抽象クラスで実装/継承
// 参考
// 再生機能の基本コントローラー(インターフェース)をおさえ、抽象的な継承先でCDコンポ、mp3プレーヤーみたいなものをつくりたい。
interface cotrolPanel {
    /*継承先のメソッドの所有を明示・保証*/
    public function play();
    public function stop();
    public function next();
    public function back();
}
interface display {
    /*継承先のメソッドの所有を明示・保証*/
    public function outDisplay();
}
abstract class player {
    /*継承先で扱う抽象概念を明示*/
    adstract protected function readFormat(){
        /*実装はしないor途中まで記述*/
    }
    adstract protected function outSpeaker(){
        /*実装はしないor途中まで記述*/
    }
}
class mp3player extends player implements controlPanel, display { 
    protected function readFormat() { ・・・}
    protected function outSpeaker() { ・・・}
    public function play() {・・・}
    public function stop() {・・・}
    public function next() {・・・}
    public function back() {・・・}
    public function outDisplay() { ・・・}
}

トレイト

PHP 5.4 から実装された機能。
処理する概念が [ A is a B ] であれば通常のクラス継承で十分だが [ A has a B ] の時は難しいケースがある。その際にBを子クラスではなくモジュール ( 汎用的かつ交換可能な部品 ) としてまとめられる構造体定義のこと。メソッド・プロパティを有する(再利用が前提なので殆どpublic)。継承(extends)はできず、使用する時はクラス内で [ use trait_name; ] を宣言する。

trait fuga {
    public function seyHi() {
        echo "Hi!!\n";
     }
     public $var;
}
class hoge{
    use fuga; // trait 使用宣言   
}
$obj = new hoge();
$obj->seiHi();
$obj->$var = 10;

永続化インスタンスとシリアライズ

生成したインスタンスは通常、プログラムの処理終了と同時にメモリ解放されて消えてしまう。しかし「敵キャラの残りHP」や「お買い物カゴ」など、ある特定のタイミングまで持ちまわりたいインスタンスがある。PHPではそういった場合に、インスタンスを一旦文字列化して他処理に渡したり、DB格納したりしている。

$obj = new hoge();
$str = serialize($obj); // serializeで文字列化
$obj2 = unserialize($str); // unserializeで戻す

通常はシリアライズできないもの(リソース)や、逆にシリアライズが不要なものをシリアライズの対象外としてあらかじめ指定するために_sleep()を定義することがある。(シリアライズ時に自動で呼ばれるマジックメソッド)
sleep()と対をなす、unserialize()が実行されるタイミングで呼ばれるマジックメソッドwakeup()もある。

参照渡しとクローン

配列などの実体データと違い、生成されたインスタンスが変数に格納されたとき、この変数の中身はインスタンスそのものではなく「インスタンスを参照する値」が入っていることに注意する。

// ex) 浅いコピー(インスタンス参照値をコピーしている)
class foo {
    public $value;
}
$obj = new foo();
$obj->i = 1;
$obj2 = $obj;
$obj2->i = 999;
var_dump($obj);
var_dump($obj2);

既にインスタンスを生成し、中身をいじったりして初期状態ではない状態で、"インスタンスをコピーしたい"と考えたとき、変数の代入では参照の値が渡されてしまいこれを実現できない。この時使うのが clone 書式。

class hoge {
    public $i;
}
$obj = new hoge();
$obj->i = 1;
$obj2 = clone $obj; // 代入ではなくcloneを使う
$obj2->i_ = 999; // 片方だけ値を変更
var_dump($obj); // 保持する $i は 1
var_dump($obj2); // 保持する $i は 999

浅いコピーと深いコピー(clone)

インスタンス自身がインスタンスを保持しているとき、cloneしても保持しているインスタンスは「参照渡し」の状態になってしまう。これを浅いコピーと呼ぶ。 cloneをした時に自動的に呼ばれるマジックメソッド__clone()を使ってこれを解決する。

class hoge {
    public function __clone() {
      $this->obj = clone $this->obj; 
    // プロパティのうち「インスタンス型のもの」は全てcloneしておく
  }
}

応用/設計知識

自身でクラス設計をするような場面では、オブジェクト指向だけでなく「その使用言語ならではの特性」を理解しておく必要がある。

基本はクラス継承だが、その根幹には機能やデータ概念の抽象化により、具体的な実装コードによるオブジェクト同士の汚染を防ぐという大前提があることを忘れない。

オブジェクトの継承関係

汎化

  • [ A is a B ] 酢豚 は 中華料理 である(逆は不成立)
  • 中華料理[親:B] -継承-> 酢豚[子:A]
  • 通常のクラス継承で実装しやすい

集約(コンポジション)

  • [ A has a B ] 中華料理 は 酢豚を含む(逆は不成立)
  • 中華料理[親:A] -継承-> 酢豚[子:B]
    • ※クラス継承よりも、クラス(構造体)とモジュール(部品)で分けたい場面がある
  • [ 酢豚はピーマンを含む 酢豚 -継承?-> ピーマン ]
    • これについては汎用的なモジュールとして切り出す手段が取られることがある→後述「トレイト」
    • PHP以外の言語ではこの has-a 関係で機能のみの拡張をすることをコンポジションと呼ぶ
    • ※厳密には集約とコンポジションはびみょーに違うらしいよ

機能の「モジュール化」

通常のプログラミングにも求められるが、オブジェクト指向プログラミングでは特に一つ一つの機能の「モジュール化」を意識している。「モジュール化」を行うときには、以下 3 点に気を付ける。

疎結合

モジュール同士が結合していない。片方のモジュールの修正に、もう片方が引っ張られたりしない。

凝集

モジュールは、適切な文脈で機能が凝集され、また不適切な文脈では機能を凝集しない。具体的には、「似たような処理だから」という理由で似たような処理が同じクラスに同席させたりしない。「あるデータの取り扱い」といった文脈で機能を凝集すべき。

状態と副作用

インスタンスの生成・探索・実行など様々な過程で、インプットとアウトプットが1つずつで副作用がなく、状態が明示的なモジュールが望ましい。

Staticメソッド(静的メソッド) をどうするか

あるまとまったデータ・処理の塊をクラスとして分けるときに、そのクラスを「静的なクラス」として扱うか、実際にインスタンス化してオブジェクトクラスとして扱うか悩むときがある。

基本的に「状態を持つか」「システムの中で複数存在するエンティティか」が分かれ目になる。まず、大前提として「動的クラス・インスタンスメソッドを使う」ところを考え、場合によってはその他を検討する。

グローバル変数・関数のまとまりのようなクラスなら、おそらくほとんど変更されない初期プロパティのまま様々な箇所でStaticに呼び出される「静的クラス」になるだろうし、反対に「インスタンス化したオブジェクト毎に状態を持つ」ようなまとまりは、やはり動的なクラスにしたほうが良い。

さっぱり状態を持たない「メソッドの部品」ならおそらくトレイトになるだろうし、継承先クラスに制限をかけたりする場合はインターフェースや抽象クラスを使うべきである。

名前空間をどう分けるか

use の使い方/使わせ方

  • PHPの名前空間はパッケージに相当する概念である
  • 同時に使うクラス、インターフェースなどを同じ名前空間に配置するべきである
  • 逆に言えば、同時に使わないクラスは同じ名前空間に配置してはならない
  • あるパッケージの内部のみで使用するクラスは一段階深い階層に配置し内部パッケージとする
  • パッケージ設計の原則を当てはめるとよい設計になりそう(自信ない)
  • useするクラスが膨らむ場合は「名前空間」をuseしても良いかも。
  • useするとせっかく分けた名前空間を横断して様々な依存が生まれる認識を。
  • use \Path\To\Class as Class; のように別名をつけて使いやすく。

パッケージ設計で名前空間を考える

REP: Reuse-Release Equivalency Principle(再利用・リリース等価の原則)

再利用の単位とリリースの単位は等価になる。

CRP: Common Reuse Principle (全再利用の原則)

パッケージに含まれるクラスは、すべて一緒に再利用される。つまり、パッケージに含まれるいずれかのクラスを再利用するということは、その他のクラスもすべて再利用することを意味する。

CCP: Common Closure Prinsiple (閉鎖性共通の原則)

パッケージに含まれるクラスは、みな同じ種類の変更に対して閉じているべきである。パッケージに影響する変更はパッケージ内のすべてのクラスに影響を及ぼすが、他のパッケージには影響しない。

ADP: Acyclic Dependencies Principle (非循環依存関係の原則)

パッケージ依存グラフに循環を持ち込んではならない。

SDP: Stable Dependencies Principle(安定依存の原則)

安定する方向に依存せよ。

SAP: Stable Abstractions Principle(安定度・抽象度等価の原則)

パッケージの抽象度と安定度は同程度でなければならない。


デザインパターン

ソフトウェア開発におけるデザインパターン(型紙(かたがみ)または設計パターン、英: design pattern)とは、過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。 ( wikipedia )

関心の分離原則

一つの複雑なシステムを開発する時、システムをお互いに影響がない(出来るだけ少ない)ような独立した個別部品に分割して、それぞれ実装していくという手法。部品と部品の間のインタフェースを固め、各部品ができるだけ単一の機能を実現し、お互いに内部の実装を気にしない(関心しない)こと。

  • 各部品間の影響が少なく、新規実装が容易
  • 開発者は担当した部分に集中できる→品質向上
  • システムが機能単位で検証・テスト可能
  • 障害発生時、切り分けが容易
  • モジュール・インターフェースを複数保持することや切り替えができる

設定より規約なの?

上記のような「モジュール間がお互いに分離されて」おり、いくつもの機能からなる複雑なシステムでは、モジュール間のやりとりを「規約」「暗黙的なルール」で縛る・統一するのが基本。「設定」は要素が増えるごとに増えていきやがて初期JavaのStrutsのように設定XMLのボリュームが人間に処理できる範囲を超えてしまう。規約であれば(しかもそれがモジュール間のやりとりにフォーカスしたものであれば)基本的に増えつづけるようなことはない。RubyOnRailsが提唱し、現在のシステム設計の基礎の考え方になっている。

制御の反転と依存性注入

Dependency-Injection

( 依存性の注入 ) とはいったものの、依存性を注入ってなんやねん。簡単に言うと「ある機能を提供するオブジェクト(サービス)」を「その機能を利用するオブジェクト(クライアント)」に渡して、依存処理部分の実装をクライアント側(サーバとクライアントのクライアントじゃないよ、サービスの利用者・オブジェクトの意味)に注入することを指す。

// DIパターンなやつ
class Client{
    private $service;
    public function __construct(Service $service) {
        $this->service = $service;
    }
    public function doSomething() {
        $this->service->doSomething();
    }
    ...
class Service{
    public function doSomething(){
        ...
    }
// -----------------------------
// DIぱたーんぢゃないやつ
class Client{
    private $service;
    public function __construct() {
        $this->service = new service();
    }
    public function doSomething() {
        $this->service->doSomething();
    }
    ...
class Service{
    public function doSomething(){
        ...
    }

上記例では、オブジェクトの生成と使用が分離されている 。new時に引数はいるのか?とかそういった部分が全部隠匿されてる。クライアントが自主的にサービスを呼ぶのではなく、サービスがクライアントに(自動的に)注入される仕組み。つまり、制御が反転している。

MVCフレームワークが提供する「処理・制御の反転」の、より狭義な、より実装よりな、より実際的な部分の設計パターンのこと。これにより開発者は「呼ばれる処理を書く」ことに専念でき、オブジェクト間をより疎結合に保てる。

ちなみにこのDIパターンを楽に実装するために、オブジェクトの生成設定をまとめたオブジェクトを提供する「らくらくDIパターン設定ライブラリ」がある、これが俗にいうDIコンテナ。

これも補足で、DIコンテナの誤った利用方法でオブジェクトの依存先を「元オブジェクト」「コンテナオブジェクト」の2つにしてしまうサービスロケータというアンチパターンもある。

Factory Method パターン

コンストラクタを外部からいじいじされたくないよね?ってことだよね。

class Robot {
    private $name = '';
    private $color;
    public static function createRedRobot($name) {
        return new self($name, 'red');
    }
    public static function createBlueRobot($name) {
        return new self($name, 'blue');
    }
    private function __construct($name, $color) {
        $this->setName($name);
        $this->color = $color;
    }
    public function setName($name) {
        $this->name = (string)filter_var($name);
    }
    public function getName() {
        return $this->name;
    }  
    public function getColor() {
        return $this->color;
    }    
}

// 普通に呼ぶ
$a = Robot::createRedRobot('ロボ太郎');
echo $a->getColor(); // red

// コンストラクタをいじって private な $color いじってやるぜ...
$a->__construct('ロボ太郎', 'blue'); // エラーではじかれる
echo $a->getColor(); // red

// これでオブジェクトの不変性を保てる