カレー職人でたとえる新人向けオブジェクト指向入門

概要
==================

新人教育のため、オブジェクト指向開発をカレーライス職人にたとえモデル化・概念の大枠を理解する。

オブジェクト指向とは
-------------------

オブジェクト指向とは現実世界のオブジェクト同士の関連をプログラミングコードで表現し、それぞれのオブジェクトに属性（メンバ変数・プロパティ）や振る舞い(メソッド)を記述する。
そして各オブジェクト間のやり取り(メッセージ)で複雑なシステムを表現する方法。

オブジェクト指向開発
-------------------

オブジェクト指向を元にシステムを構築していく開発方法

オブジェクト指向言語
-------------------

言語レベルでのオブジェクト指向をサポートしてる状態

なぜこの開発手法が必要なのか
-------------------

スクリプト処理のように必要な処理を上から下にくスタイル(手続き型プログラミング)では、一般的に
開発スピードは加速するが、チーム開発の場合保守性・運用性などが損なわれる。
オブジェクト指向開発は手続き型に比べチーム開発、保守性・運用性が向上する。
またこの開発手法は長年業界内でもまれ、一定の成果をだしているためチームでの開発手法で採用されるケースが多いためもある。

オブジェクト指向の構成要素
==================
オブジェクト指向の考え方は複数の考え方に基づいて構成されます。
各構成をプログラミングコードと一緒に説明します。


クラス
---------------
オブジェクトの設計図にあたる部分
例 カレーライス職人

```php
/**
* このクラスはカレーライス職人を表現しています。
*/
class CurryCookParent{}
```

プロパティ（メンバ変数）
---------------
オブジェクトに対する属性を表現するもの
例 スパイスの種類、ご飯の種類、カレーライスの重量、カレーライス

```php
/**
* このクラスはカレーライス職人を表現しています。
* この職人はカレーのスパイス、ご飯の種類、ご飯の量、できがったカレーライスを扱うことができます。
*/
class CurryCookParent{
    var $spice = array('辛いスパイス');
    var $gohan = '白米';
    var $weight = 200;
    var $dish = array();
}
```

メソッド
----------

オブジェクトが表現できる振る舞い。
例 スパイスの調合、ご飯を盛る、ご飯を減らす、カレーを作る、カレーを配る。

```php
/**
* このクラスはカレーライス職人を表現しています。
* この職人はカレーのスパイス、ご飯の種類、ご飯の量、できがったカレーライスを扱うことができます。
* 辛いスパイス以外にも他のスパイスを混ぜ合わせることができます。
* またご飯の量を増やしたり減らしたり、カレーを作ったり配給することもできます。
*/
class CurryCookParent{
    var $spice = array('辛いスパイス');
    var $gohan = '白米';
    var $weight = 200;
    var $dish = array();

    /**
    * スパイスを調合する
    */
    function mixed($spice){
        $this->spice[] = $spice;
    }

    /**
    * ご飯を盛る
    */
    function add(){
        $this->weight += 200;
    }
    
    /**
    * ご飯を減らす
    */
    function remove(){
        $this->weight -= 200;
    }
    
    /**
    * カレーライスを作る
    */
    function cook(){
        $this->dish = array($this->spice, $this->gohan, $this->weight);
    }
    
    /**
    * カレーライスを配る
    */
    function distribute(){
        return $this->dish;
    }
    
}
```

可視性
-------------
オブジェクトのプロパティ、メソッドについて使用範囲について制限をかけること
例 ご飯は他人に入れてもらってもいいが、スパイスの調合が職人だけが扱いたいなど

```php
/**
* このクラスはカレーライス職人を表現しています。
* この職人はカレーのスパイス、ご飯の種類、ご飯の量を扱うことができます。
* 辛いスパイス以外にも他のスパイスを混ぜ合わせることができます。
* またご飯の量を増やしたり減らしたりできるようになりました。
* スパイスの調合は職人だけができるようになりました。
* ご飯の量は職人以外の人でも扱えるようになりました。
*/
class CurryCookParent{
    protected $spice = array('辛いスパイス');
    protected $gohan = '白米';
    protected $weight = 200;
    protected $dish = array();

    /**
    * スパイスを調合する
    */
    protected function mixed($spice){
        $this->spice[] = $spice;
    }

    /**
    * ご飯を盛る
    */
    public function add(){
        $this->weight += 200;
    }
    
    /**
    * ご飯を減らす
    */
    public function remove(){
        $this->weight -= 200;
    }
    
    /**
    * カレーライスを作る
    */
    public function cook(){
        $this->dish = array($this->spice, $this->gohan, $this->weight);
    }
    
    /**
    * カレーライスを配る
    */
    public function distribute(){
        return $this->dish;
    }
    
}
```

インスタンス
-------
クラスを元に作成されたオブジェクトの実態物。
例 カレーライス職人プログラムコードの上に呼び出して、職人がプログラム上に存在すること。

```php
//式の右辺がレシピを手に入れる動作
//式の左辺がレシピを手に入れて作業する準備が整った状態
$CurryCookParent = new CurryCookParent();
```


インスタンス化
----------
クラスを元にオブジェクトを作成すること。
例 職人を手に入れること。

```php
//職人を手に入れる動作
new CurryCookParent();
```

コンストラクタ
-----------

インスタンス化する時に初期化される場所
例 カレー職人を呼びだす時に今日がカレー職人が営業日か調べる。

```php
/**
* このクラスはカレーライス職人を表現しています。
* カレー職人を呼び出したときに今日が営業びか確認
* この職人はカレーのスパイス、ご飯の種類、ご飯の量を扱うことができます。
* 辛いスパイス以外にも他のスパイスを混ぜ合わせることができます。
* またご飯の量を増やしたり減らしたり、カレーを作ったり配給することもできます。
* スパイスの調合は職人だけができるようになりました。
* ご飯の量は職人以外の人でも扱えるようになりました。
* 営業日を確認するようになりました。
*/
class CurryCookParent{
    protected $spice = array('辛いスパイス');
    protected $gohan = '白米';
    protected $weight = 200;
    protected $dish = array();

    /**
    * 営業日をチェック
    */
    public function __construct(){
        $day = date('w');
        if(in_array($dat, array(1,2,3,4,5,6,7))){
            echo('毎日営業日');
        }
    }
    
    /**
    * スパイスを調合する
    */
    protected function mixed($spice){
        $this->spice[] = $spice;
    }

    /**
    * ご飯を盛る
    */
    public function add(){
        $this->weight += 200;
    }
    
    /**
    * ご飯を減らす
    */
    public function remove(){
        $this->weight -= 200;
    }
    
    /**
    * カレーライスを作る
    */
    public function cook(){
        $this->dish = array($this->spice, $this->gohan, $this->weight);
    }
    
    /**
    * カレーライスを配る
    */
    public function distribute(){
        return $this->dish;
    }
    
}
```

デストラクタ
-----------

インスタンスを破棄される前の場所
例 カレーライスを片付ける

```php
/**
* このクラスはカレーライス職人を表現しています。
* カレー職人を呼び出したときに今日が営業びか確認
* この職人はカレーのスパイス、ご飯の種類、ご飯の量を扱うことができます。
* 辛いスパイス以外にも他のスパイスを混ぜ合わせることができます。
* またご飯の量を増やしたり減らしたり、カレーを作ったり配給することもできます。
* スパイスの調合は職人だけができるようになりました。
* ご飯の量は職人以外の人でも扱えるようになりました。
* 営業日を確認するようになりました。
* 食べ終わったカレーライスを片付けるようになりました。
*/
class CurryCookParent{
    protected $spice = array('辛いスパイス');
    protected $gohan = '白米';
    protected $weight = 200;
    protected $dish = array();

    /**
    * 営業日をチェック
    */
    public function __construct(){
        $day = date('w');
        if(in_array($dat, array(1,2,3,4,5,6,7))){
            echo('毎日営業日');
        }
    }

    /**
    * カレーライスを片付ける
    */
    protected function __destruct(){
        $this->dish = null;
    }
    
    /**
    * スパイスを調合する
    */
    protected function mixed($spice){
        $this->spice[] = $spice;
    }

    /**
    * ご飯を盛る
    */
    public function add(){
        $this->weight += 200;
    }
    
    /**
    * ご飯を減らす
    */
    public function remove(){
        $this->weight -= 200;
    }
    
    /**
    * カレーライスを注文する
    */
    public function order(){
        $this->dish = array($this->spice, $this->gohan, $this->weight);
    }
    
    /**
    * カレーライスを配る
    */
    public function distribute(){
        return $this->dish;
    }
    
}
```

例外
--------------------
クラスまたはメソッドの前提条件が破られる状態
例　カレーライス職人を営業日外でインスタンス化したとき。
この場合の前提条件はカレーライス職人は営業日にしか働かない。


```php
/**
* このクラスはカレーライス職人を表現しています。
* カレー職人を呼び出したときに今日が営業びか確認
* この職人はカレーのスパイス、ご飯の種類、ご飯の量を扱うことができます。
* 辛いスパイス以外にも他のスパイスを混ぜ合わせることができます。
* またご飯の量を増やしたり減らしたり、カレーを作ったり配給することもできます。
* スパイスの調合は職人だけができるようになりました。
* ご飯の量は職人以外の人でも扱えるようになりました。
* 営業日を確認するようになりました。
* 食べ終わったカレーライスを片付けるようになりました。
* 営業日でない場合知らせることができるようになりました。
*/
class CurryCookParent{
    protected $spice = array('辛いスパイス');
    protected $gohan = '白米';
    protected $weight = 200;
    protected $dish = array();
    
    /**
    * 営業日であるなら、職人を召還する
    * 営業日でない場合、職人は召還されず、お客さんに休日と伝える
    */
    public function __construct(){
        $day = date('w');
        if(in_array($dat, array(1,2,3,4,5))){
            throw new Exception('今日は休日です。');
        }
    }

    /**
    * カレーライスを片付ける
    */
    protected function __destruct(){
        $this->dish = null;
    }
    
    /**
    * スパイスを調合する
    */
    protected function mixed($spice){
        $this->spice[] = $spice;
    }

    /**
    * ご飯を盛る
    */
    public function add(){
        $this->weight += 200;
    }
    
    /**
    * ご飯を減らす
    */
    public function remove(){
        $this->weight -= 200;
    }
    
    /**
    * カレーライスを注文する
    */
    public function order(){
        $this->dish = array($this->spice, $this->gohan, $this->weight);
    }
    
    /**
    * カレーライスを配る
    */
    public function distribute(){
        return $this->dish;
    }
    
}
```

継承
-----------
クラスを拡張すること(縦の拡張)
継承されたクラスは継承もとのプロパティ、メソッドといった性質は引き継がれる。(親の性質は子に引き継がれる)
例　カレーライス職人の元で修行して、スキルを身につけた若手のカレーライス職人

```php
class CurryCookParentChild extends CurryCookParent{
}
```

親クラス
-----------
自クラスからみて継承元になるクラス

例 CurryCookParentChildから見た場合CurryCookParentさんにあたる。

子クラス
---------

自クラスからみて継承先になるクラス
例 CurryCookParentから見た場合CurryCookParentChildさんにあたる。


オーバーライド
---------
親クラスの定義を再定義すること。
例 若手カレーライス職人は親分よりライスの盛り幅が大きい
ただし親分の元で修行したため、スパイスの調理方法やご飯の種類は変更されない。

```php
class CurryCookParentChild extends CurryCookParent{

    /**
    * ご飯を盛る
    * 親分より100g多く盛る
    */
    public function add(){
        $this->weight += 300;
    }
    
    /**
    * ご飯を減らす
    * 親分より100g減らす
    */
    public function remove(){
        $this->weight -= 100;
    }
}
```