知らなきゃ現場でやばい!PHPのオブジェクト指向とクラス(初心者向け)

# 参考資料

https://www.youtube.com/watch?v=RMwzAXFwup0&list=PLErg7aSNT21xAVbJAEWS1oxgGLL__ySK2&index=8


https://qiita.com/Hashimoto-Noriaki/items/f3fc6d716e925e3c500a

https://beyondjapan.com/blog/2023/01/php-constructor/



# オブジェクト指向とは
### クラス
```クラス```とは***変数、定数、関数をひとまとめにした***設計図と思ってください。
***プログラミングでこのクラスを使って組み立て方または考え***を```オブジェクト指向```と言います。

### クラスを使う理由
理由は***同じような設計図は何回も使うのが面倒い***からです。

ex)
ドラえもんを作る時に1回設計図を作ってからドラえもんを作ります。
設計図もなしに作るのは難しいですからね。
そのドラえもんの設計書をベースにドラミちゃんやミニドラなどの他の猫型ロボットを作っていくイメージです。

### クラスの定義
クラスは以下のように定義します。

```php
クラスの定義方法
//class クラス名{ //クラス名は大文字スタート
    //実行内容
//}
```
ポケモンをベースにお話をします。
HPのようなダメージを受けた時にHPが減って***変動するもの***を```メンバー変数```です。
戦うや逃げるなどのコマンドで逃げたら逃げたと表示されたたかう時は
10万ボルトで攻撃した時に攻撃したと表示されます。これが```メンバーメソッド```です。
ここでは技の選択などはないものとして考えます。
```php
//クラス/オブジェクト指向
//設計図/クラスを使ったプログラミングの組み立て方
//ポケモンがたたかう、道具を使う、ポケモンを入れ替える、逃げるコマンドが書かれた設計書
//自分のポケモン、あなたのポケモンで毎回設計書を作るのは、面倒。使いまわす
//紙1枚の設計図だけでは意味がないので、実際のポケモンを作って動かす。(オブジェクト)

class Pokemon
{
    //メンバ変数　HP
    public $HP;

    //メンバ変数　、戦う
    function attack()
    {
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }
}
```
実際にポケモンやトレーナーを動かす時に```オブジェクト化```します。
以下のように実行します。
1.```クラスをオブジェクト化```して使う(動的)
2.```$オブジェクト名　= new クラス名(引数);```
3.```$オブジェクト名->メンバ変数　= 10;```
4.```$オブジェクト名->メンバメソッド();```
```->```は```アロー演算子``` と言います。

```php
<?php
//クラスの定義方法
//class クラス名{
//実行内容
//}

class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //メンバ変数
    //戦う
    function attack()
    {
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 10; //ポケモンのHP
//オブジェクトの中身を見る
print_r($new_pokemon);
echo "<br>";
//Pokemon Object ( [hitPoint] => 10 )  //出力結果
```
出力結果が ***Pokemon Object ( [hitPoint] => 10 )*** となります。
次はメンバメソッドを実行していきます。
```php
<?php
class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //メンバメソッド
    //戦う
    function attack()
    {
        echo "10万ボルト<br>";
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
//戦うのメンバーメソッドを実行
$new_pokemon->attack();
echo "<br>";

//10万ボルト
```

### 設計図のまま使う
オブジェクト化しなくても```設計図(クラス)のまま使う```ことができます。
***実務でよく使うみたい***です。
function attack()の横に```static```を追記し、
```クラス名::メンバメソッド```を使います。

```php
<?php
//クラス/オブジェクト指向
//設計図/クラスを使ったプログラミングの組み立て方
//ポケモンがたたかう、道具を使う、ポケモンを入れ替える、逃げるコマンドが書かれた設計書
//自分のポケモン、あなたのポケモンで毎回設計書を作るのは、面倒。使いまわす
//紙1枚の設計図だけでは意味がないので、実際のポケモンを作って動かす。(オブジェクト)

class Pokemon 
{
    //メンバ変数　HP
    public $hitPoint;

    //メンバメソッド　　たたかう(技は10万ボルトだけにします。)
    public static function attack (){
        echo "10万ボルト<br>";
    }

    //メンバメソッド　　道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモンを変える<br>";
    }

    //逃げる
    function escape (){
        echo "逃げる<br>";
    }

}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 20; //ポケモンのHP
//戦うのメンバーメソッドを実行
//$new_pokemon->attack()
// 静的メソッドの呼び出し
Pokemon::attack();

//10マン
```

### メンバメソッド、関数に引数を持たせる
7ポイントのダメージをポケモンに与えたという処理を実行していきます。

```php
class Pokemon 
{
    //メンバ変数　HP
    public $hitPoint;

    //メンバメソッド　　たたかう(技は10万ボルトだけにします。)
    function attack ($point){
        echo "攻撃によって、相手のポケモンに" . $point . "のダメージ<br>";
    }

    //メンバメソッド　　道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモンを変える<br>";
    }

    //逃げる
    function escape (){
        echo "逃げる<br>";
    }

}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 20; //ポケモンのHP
//戦うのメンバーメソッドを実行
//$new_pokemon->attack()
//メンバメソッドの引数 
$new_pokemon->attack(7);

//攻撃によって、相手のポケモンに7のダメージ
```


# コンストラクタ
これは***クラスをインスタンス化（オブジェクト化）した時に、必ず実行されるメソッド***で、
***クラスを初期化する関数をイメージ***するといいみたいです。

クラスの中の ***$thisはクラスの全体***のことです。
クラスの中のHPのメンバ変数を呼び出す場合は```$this->hitPoint```で呼び出せます。

```php
<?php
class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //初期化メソッド
    public function initial()
    {
        $this->hitPoint = 40;
        echo "最初のHPは" . $this->hitPoint . "だぞ！";
    }

    //メンバ変数
    //戦う
    // static function attack()
    // {
    //     echo "戦う<br>";
    // }
    function attack($point)
    {
        echo "攻撃によって、相手のポケモンに" . $point . "のダメージ<br>";
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 10; //ポケモンのHP
//オブジェクトの中身を見る
print_r($new_pokemon);
echo "<br>";
//戦うのメンバーメソッドを実行
//$new_pokemon->attack();
//Pokemon::attack();

//メンバメソッドの引数
$new_pokemon->attack(7);


//Pokemon Object ( [hitPoint] => 10 ) 
//攻撃によって、相手のポケモンに7のダメージ
//最初のHPは40だぞ！
```

だけどもっと楽な方法もあります。

初期化のコンストラクタの呼び出し方を以下のように変更できます。

```php
<?php
class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //初期化メソッド
    public function __construct()
    {
        $this->hitPoint = 40;
        echo "最初のHPは" . $this->hitPoint . "だぞ！<br>";
    }

    function attack($point)
    {
        echo "攻撃によって、相手のポケモンに" . $point . "のダメージ<br>";
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 10; //ポケモンのHP
//オブジェクトの中身を見る
print_r($new_pokemon);
echo "<br>";
//戦うのメンバーメソッドを実行
//$new_pokemon->attack();
//Pokemon::attack();

//メンバメソッドの引数
$new_pokemon->attack(7);

//最初のHPは40だぞ！
//Pokemon Object ( [hitPoint] => 10 ) 
//攻撃によって、相手のポケモンに7のダメージ
```
initialは使わず```最初の__constructを使えばinitialを呼び出さずとも初期の段階で出力```できます。

# アクセス修飾詞
上のコードでも登場した```public```のことです。アクセス修飾詞は3つ知っておけばいいみたいです。
|アクセス修飾詞|説明|
|--|--|
|public|どこからでも呼び出せるメソッド、変数|
|private|同じクラスの中で呼び出した時に正常に動作|
|protected|クラス内でアクセスされるか、そのクラスと親子関係にある子どものクラス内で、使われるべきメソッド、およびメンバ変数|

### private
privateは外部から呼び出したくない時に使います。
publicの方が便利ですが、必ずしもベストなやり方ではなくて
勝手に外部から使われないために使ったりします。

```php
<?php
class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //初期化メソッド
    public function __construct()
    {
        $this->hitPoint = 40;
        echo "最初のHPは" . $this->hitPoint . "だぞ！<br>";
    }

//ここでは省略

    
    //攻撃されたからHPが減る
    public function pokemon_attacked($point)
    {
        $this->pokemon_damaged($point); //攻撃を受けたメッセージ表示　 下のpokemon_damagedから呼び出されている
        $this->hitPoint -= $point; //HPが減る
        echo "残りHPは" . $this->hitPoint . "だ！<br>";
    }
    //ダメージを受けた
    private function pokemon_damaged($point)
    {
        echo "相手のポケモンからダメージを受けた<br>";
        echo $point . "のダメージ<br>";
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();

//アクセス修飾子
$new_pokemon->pokemon_attacked(5);

//最初のHPは40だぞ！
//相手のポケモンからダメージを受けた
//5のダメージ
//残りHPは35だ！
```
pokemon_damagedはpokemon_attackedの中だけで使われることになります。
外部から勝手にHPとか減らされたら通信バトルとかすると全部負けちゃいますからね汗。

### protected
クラスの親子関係にある子どものクラス内で使われるメソッドです。
ポケモンクラスとは違う新しいクラスのポケモンのタイプクラスを定義していきます。
タイプの中でも炎タイプで定義していきます。

```php
<?php
class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //初期化メソッド
    public function __construct()
    {
        $this->hitPoint = 40;
        echo "最初のHPは" . $this->hitPoint . "だぞ！<br>";
    }


    //メンバ変数
    //戦う
    // static function attack()
    // {
    //     echo "戦う<br>";
    // }
    function attacked($point)
    {
        echo "攻撃によって、相手のポケモンに" . $point . "のダメージ<br>";
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }


    //攻撃されたからHPが減る
    public function pokemon_attacked($point)
    {
        $this->pokemon_damaged($point); //攻撃を受けたメッセージ表示　 下のpokemon_damagedから呼び出されている
        $this->hitPoint -= $point; //HPが減る
        echo "残りHPは" . $this->hitPoint . "だ！<br>";
    }
    //ダメージを受けた
    private function pokemon_damaged($point)
    {
        echo "相手のポケモンからダメージを受けた<br>";
        echo $point . "のダメージ<br>";
    }
}

//クラスの親子
class fireType extends Pokemon
{
    //かえんほうしゃ
    public function Charizard()
    {
        echo "リザードンのかえんほうしゃ<br>";
        $this->attacked(30);
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 40; //ポケモンのHP


//メンバメソッドの引数
//$new_pokemon->attack(7);

//コンストラクタ 
//$new_pokemon->initial();

//アクセス修飾子
$new_pokemon->pokemon_attacked(5);

//クラスの親子関係
$fireType = new firetype();
$fireType->Charizard();
$fireType->attacked(30);
$fireType->pokemon_attacked(30);

//最初のHPは40だぞ！
//相手のポケモンからダメージを受けた
//5のダメージ
//残りHPは35だ！
//最初のHPは40だぞ！
//リザードンのかえんほうしゃ
//攻撃によって、相手のポケモンに30のダメージ
//相手のポケモンからダメージを受けた
//30のダメージ
//残りHPは10だ！
```

リザードンは戦うし、ダメージも受けますよね。
そのためにポケモンクラスから炎タイプに関数を引き継いでいくようにします。
変数を引き継ぎたい場合は```extends(継承する)```を書きます。
Pokemonという親クラスからfireType(炎タイプ)というクラスに変数や関数を引き継ぎます。

ここで本題の```protected```を使っていきます。自分のクラスと親子関係にある子クラスでも使えます。

```php
<?php
class Pokemon
{
    //メンバ変数　HP
    public $hitPoint;

    //初期化メソッド
    public function __construct()
    {
        $this->hitPoint = 40;
        echo "最初のHPは" . $this->hitPoint . "だぞ！<br>";
    }


    //メンバ変数
    //戦う
    // static function attack()
    // {
    //     echo "戦う<br>";
    // }
    protected function attacked($point)
    {
        echo "攻撃によって、相手のポケモンに" . $point . "のダメージ<br>";
    }

    //メンバメソッド
    //道具
    function items()
    {
        echo "道具を使う<br>";
    }

    //手持ちポケモン
    function my_pokemon()
    {
        echo "ポケモン<br>";
    }

    //逃げる
    function escape()
    {
        echo "逃げる<br>";
    }


    //攻撃されたからHPが減る
    function pokemon_attacked($point)
    {
        $this->pokemon_damaged($point); //攻撃を受けたメッセージ表示　 下のpokemon_damagedから呼び出されている
        $this->hitPoint -= $point; //HPが減る
        echo "残りHPは" . $this->hitPoint . "だ！<br>";
    }
    //ダメージを受けた
    private function pokemon_damaged($point)
    {
        echo "相手のポケモンからダメージを受けた<br>";
        echo $point . "のダメージ<br>";
    }
}

//クラスの親子
class fireType extends Pokemon
{
    //かえんほうしゃ
    function Charizard()
    {
        echo "リザードンのかえんほうしゃ<br>";
        $this->attacked(30);
    }
}

//オブジェクト化して作成
$new_pokemon = new Pokemon();
$new_pokemon->hitPoint = 40; //ポケモンのHP
//オブジェクトの中身を見る
// print_r($new_pokemon);
// echo "<br>";
//戦うのメンバーメソッドを実行
// $new_pokemon->attack();
// Pokemon::attack();

//メンバメソッドの引数
//$new_pokemon->attack(7);

//コンストラクタ 
//$new_pokemon->initial();

//アクセス修飾子
$new_pokemon->pokemon_attacked(5);

//クラスの親子関係
$fireType = new firetype();
$fireType->Charizard();
//$fireType->attacked(30);
$fireType->pokemon_attacked(30);


//最初のHPは40だぞ！
//相手のポケモンからダメージを受けた
//5のダメージ
//残りHPは35だ！
//最初のHPは40だぞ！
//リザードンのかえんほうしゃ
//攻撃によって、相手のポケモンに30のダメージ
//相手のポケモンからダメージを受けた
//30のダメージ
//残りHPは10だ！
```