PHPにおけるクラスの使い方

ここでは一般的なクラスやabstract、trait、interfaceなどの使い方をまとめたいと思います。

##classの使い方
クラスは変数・定数やメソッドを一つにまとめたもの。
役割ごとにクラスを作り、そのインスタンスを使ってプログラムを動かすことをオブジェクト指向という。

```php:class_example.php
class Product{
    //公開条件にはpublic、protected、privateがある。
    // publicは外から使える→インスタンス後にアクセスできるということ
    // protectedは自分と継承先のクラスが使うことができる
    // privateはクラス内でしかプロパティやメソッドにアクセスできない→変数などはprivateが安全(外から書き換えられないから)

    // 変数
    private $product = [];

    // 関数
    // コンストラクトメソッドはクラスがインスタンス化される際に呼び出される
    // $thisはnewによりインスタンス化したオブジェクトを指す
    function __construct($product=null){
        $this->product[] = $product; 
    }
    
    public function getProduct(){
        $products = $this->product;
        foreach($products as $product){
            echo $product;
        }
    }

    public function addProduct($item){
        $this->product[] = $item;
    }

    // staticはクラスメソッドを定義できる
    // Class::メソッド名()で使うことができる
    public static function getStaticProduct($str){
        echo $str;
    }
}
```

```zsh
$instance = new Product('インプット');

$instance->getProduct();
=> 'インプット'

$instance->addProduct('追加');
$instance->getProduct();
=> 'インプット'
=> '追加'

Product::getStaticProduct('静的');
=> '静的'
```

##継承
クラスは単一継承の機能を持ち、一つのクラスを継承できる。
親クラスの変数やメソッドなどを子クラスが使えるようになる。

```php
class Parente{
  protected $parentVariable = '親の変数です';

  public function parentfunc(){
    echo "親の関数です";
  }
}

class Child extends Parente{
    public function test(){
      echo $this->parentVariable;
    }
}

$instance = new Child();

$instance->test();
=> '親の変数です' // 変数のアクセス修飾子はprotectedなので継承先のクラス内でも使える

$instance->parentfunc();
=> '親の関数です'
```

##インターフェイス

継承先のクラスにメソッドの強要を行う。
インターフェイス内に書かれているメソッドは継承先のクラスで用いなければならない。
インターフェイスは中身のないpublicメソッドしか書けない、インスタンス化はできない。
継承方法は`implements`を使い、何個でも継承できる。

```php
interface ExampleInterface{
    // helloメソッドを継承先のクラスに置いて定義しなければエラーが出る
    public function hello();
}

interface ExampleInterface2{
    // goodMorningメソッドを継承先のクラスに強制
    public function goodMorning();
}

class Example implements ExampleInterface, ExampleInterface2{
    public function hello(){
        echo 'こんにちは';
    }

    public function goodMorning(){
        echo 'おはよう';
    }
}
```

どんな時に使うのか謎ですが、何かソースコードをみながら理解を深めたいと思います。

##抽象クラス

抽象クラスはクラスにインターフェイスの機能を持たせたようなクラス。(インスタンス化はできない) 
`abstract class クラス名Abstract`と定義する。
わかりやすいようにクラス名にAbstractとつける場合が多い。

メソッドの強制とメソッドを提供する。
メソッド定義の前に`abstract public(protected) 〜`とつけるとそのメソッドを継承先のクラスで強制する。

```php
<?php

abstract class ExampleAbstract{
  protected $abstractVariable = '抽象クラスの変数です';

  public function goodEvening(){
    echo 'こんばんは';    
  }

  abstract protected function hello();
}

class Example extends ExampleAbstract{
  public function hello(){
    echo 'こんにちは';
    echo $this->abstractVariable;
  }

  public function goodMorning(){
    echo 'おはよう';
  }
}

$instance = new Example();
$instance->hello();
=> 'こんにちは抽象クラスの変数です';
$instance->goodEvening();
=> 'こんばんは';
```

##トレイト

クラスは単一継承のため、一つのクラスしか継承できませんが、トレイト何個でも継承することができるクラスのようなもの(インスタンス化はできない)
`trait トレイト名`で使用する。
使うときは使いたいクラス内でuseする。


```php
trait ExampleTrait{
  protected $traitVariable = '抽象クラスの変数です';

  private $traitPrivateVariable = 'トレイトのプライベート変数です';

  public function hello(){
    echo 'こんにちは';
  }
}

trait ExampleTrait2{
  public function goodEvening(){
    echo 'こんばんは';
  }
}

class Example{ 
  use ExampleTrait;
  use ExampleTrait2;

  public function goodMorning(){
    echo 'おはよう';
    echo $this->traitVariable;
    echo $this->traitPrivateVariable;
  }
}

$instance = new Example();
$instance->goodMorning();
=>'おはよう抽象クラスの変数ですトレイトのプライベート変数です'
```

trait内で定義したprivate変数もuse先のクラスで普通に使えました。。。
traitはとても使いやすそうな感じがしました。クラスを拡張してくれる感じで。

##おわりに
メソッドの強制などはどうやって使うのか謎が深まりましたが、とりあえずphpにおけるクラスの使い方をアウトプットしました。またクラス関係で学習したものはここに追記していく予定です。