未経験からweb系プログラマーになるための独学履歴~クラスの基本からコンストラクタ・デストラクタまで~

##このコーナーについて

 私は根っからの文系なのでプログラミングや情報技術についてはITパスポート程度の知識しかなく、現在は全くの独学でコードや言語等のスキルの勉強はチュートリアル等でコードを書いて成果物を作りながら学んでいけるが、それらの過程で出てくる用語や技術についてはイマイチ学びきれない。
なので、折に触れて書籍及びQlita記事等のネットサーフィンで学んだ座学的知識をアウトプットすることがこのコーナーの目的である。

## 今回

パーフェクトPHPで学ぶクラスの基本とコンストラクタ・デストラクタ

## クラスの基本

```php:クラスを作る

<?php 
class Employee {

	private $test = 1;

	public function work() { // 1

		echo '書類を整理しています',PHP_EOL;
}


	$yamada = new Employee(); // 2

	$sasaki = new Employee();

	$yamada->work(); // 3

	$suzuki = $yamada; // 4

	$suzuki = clone $yamada; // 5

?>

```
1 
クラスを作る。設計図を書くイメージ。

2
クラスをインスタンス化する。これから設計図を使うぞって宣言だとイメージするといいかも。
なお、インスタンスはオブジェクトと呼称することもある。厳密な意味合いの違いは不明でインスタンスをオブジェクトといえば、オブジェクトをインスタンスと呼称する人もいる。
私はイメージとしてはインスタンスは設計図（クラス）を使うぞと宣言して、コピーを作り、オブジェクトはそのコピーした設計図をさらに使い回したものなのだなと大雑把に考えている。
なので、上記のようにインスタンス（オブジェクト）は同じクラスから複数作ることができる。

3
アロー演算子を使い、クラスの中にアクセスしている。
アクセスするのはキーと値がセットされているプロパティまたはクラスの中の関数であるメソッド。

4
$yamadaを$suzukiへオブジェクト参照するための橋渡しをするために使っている。
この場合、コピーされた変数(suzuki)に対する変更はコピー元の変数(yamada)にも反映される。

5
こちらは逆にオブジェクトへの参照ではなく、オブジェクトの複製。
よってオリジナルとコピーとで因果関係は生まれない。
詳しい使い方はマジックメソッドの__cloneの項目を参照。

## アクセス修飾子

```php:アクセス修飾子色々

public // クラスの外側から参照・呼び出しができる。一番アクセス権限が緩い
private // 自分のクラスの内側からのみ参照・呼び出しができない。一番アクセス権限がきつい
protected // 自分のクラスとその派生クラスの内側からのみ参照・呼び出しができる。


```

```php:使用例


<?php 
	$namae = "watanabe";
	$obj1->hanasu();
	 
	class hito{
	  private $namae;
	  function hanasu(){
	    echo "私は $this->namae です。";
	  }
	}

	$test = new hito();
	$test-> hanasu();


  ?>

```

```php:実行結果

// 私は  です。

```

実行結果は以上の通り、`$namae`の部分が空となってしまっている。
これはhitoクラスの中の`$namae`のアクセス修飾子がprivateになっているので、クラスの外にある`$namae = "watanabe";`を参照・呼び出しができていないためである。
publicであれば外側にある`$namae = "watanabe"`を参照し、クラス内の変数`$namae`に`"watanabe"`が代入されるからエラーにならず、`$test->hanasu();`が処理される。




## プロパティとメソッド

```php:プロパティとメソッドにアクセスする。


<?php


	class Employee {

		public $name; // プロパティその1
		public $state = "働いている"; // プロパティその2

		public function work() { // メソッド

		echo '書類を整理しています。',PHP_EOL;


		}

	}

	$yamada = new Employee(); // 1

	$yamada->name = "山田"; // 2

	echo $yamada->state,$yamada->name,'さん:'; // 3

	$yamada->work(); // 4

 ?>


```

```php:実行結果

// 働いている山田さん:書類を整理しています。


```

1
インスタンス化

2
プロパティにアクセスする。
`$name`はキー、今回は値がないところにアクセスして値に`"山田"`を代入するということをしている。

3
同様にプロパティにアクセス、`$state`は上記の通りなので、結果「働いてる山田さん：」と出力される。

4
メソッドにアクセス、関数の処理が実行される。

余談ではあるが、あとからキーに値を代入する場合、空（null）にしたくない場合は変数は以下のようにしておくほうがいい。

```php:変数の代入

<?php

$a = ""; // 文字列を後から値として代入したい時
$b = 0; // 数値を後から値として代入したい時

?>



```

## $this

```php:thisの使い方

<?php

	
	class Employee {
		public $name;
		private $state = '働いている';

		public function getState() { // メソッド1

			return $this->state;

		}

		public function setState($state) { // メソッド2

			$this->state = $state;
		}

		public function work() {
			echo '書類を整理しています',PHP_EOL;

		}

	}

	$yamada = new Employee();
	$yamada->name = "山田";
	
	$yamada->setState('休憩している'); // メソッドにアクセスする。
	
	echo $yamada->name,'さんは',$yamada->getState(),PHP_EOL;
?>

```
`$this`はインスタンス自身を指す特別な変数である。踏み込んで言うと『`$this`とはクラス定義内部でプログラムがアクセス可能なオブジェクト名（インスタンスメソッド）』であると言える。この場合はnew Employeeが`$this`になる。例えば、private指定されている変数stateにアクセスしたいとする。当然クラスの外からはどうこうできないので、まずクラス内にメソッド1を作る。メソッド1はprivateなプロパティである`$state`にアクセスするためのメソッド。ついで、それを変更するメソッドであるメソッド2を作る。
そして実際にsetStateメソッドにアクセスすると、Employeeクラスの中にあるsetStateメソッドにおける$thisは`$yamada`を表すことになる。
よって、処理は以下のようになる

```php:処理

<?php

	
	class Employee {
		public $name;
		private $state = '働いている';

		public function getState() { 

			return $this->state;

		}

		public function setState($state) { // 3

			$this->state = $state;
		}

		public function work() {
			echo '書類を整理しています',PHP_EOL;

		}

	}

	$yamada = new Employee();
	$yamada->name = "山田"; // 1
	
	$yamada->setState('休憩している'); // 2
	
	echo $yamada->name,'さんは',$yamada->getState(),PHP_EOL; // 4
?>


1
$nameプロパティにアクセスして、山田という値を代入（セット）する。

2
setStateメソッドにアクセスする。

3
setStateメソッドが実行される。メソッドの処理コードが

$yamada->state = $state;

となるので、$stateの値が"休憩している"に変更される。

4
「山田さんは休憩している」と表示し、改行する。

```

$thisは最初は理解しにくい人もいると思うので、参考にさせて頂いたサイト載せておくのでぜひ一読してほしい。
[ts0818のブログ：PHPで擬似変数$thisって何のためにあるのか？](https://ts0818.hatenablog.com/entry/2015/10/03/215418)

## static

```php:static

<?php 

	// staticプロパティ
	
	class Employee {

		public $name;
		public static $company = "出版社"


	}

	echo "従業員はみんな",Employee::$company,"に勤めています",PHP_EOL;


 ?>

```

プロパティやメソッドに`static`をつけるとインスタンス化しなくてもそれらにアクセスすることができる。上はその例でクラスはあるが、インスタンス宣言はしていないのにも関わらず`echo`で書き出しができている。
staticプロパティにアクセスするにはクラス名::の形で書く。
staticは静的ともいう。静的・動的についてはこちらを参考にしてほしい。

[わわわIT用語辞典 ](https://wa3.i-3-i.info/word11858.html)


## self

```php:selfについて

?php 

	class Employee {

		public static $company = "出版社";

		public function getCompany () {

			return self::$company;
		}
	}

 ?>


```

`$this`がインスタンスの代名詞のような使い方であったのに対し、クラスコンテキスト内部において`self`はそのクラス自身となる。つまり、クラスの代名詞のような使い方になる。
上の例では`self::$company`は`Employee::$company`と同義となる。
さらにこれが`getConmpany`メソッドの中に定義されているので、クラスの外からこのメソッドを使って`$company`にアクセスすることもできる。

## const

```php:constについて

<?php


	class Employee {

		const PARTTIME = 1; // アルバイト
		const REGULAR = 2; // 正社員
		const CONTRACT = 3; // 契約社員

	}

	var_dump(Employee::REGULAR); // 結果はint(2)。

 ?>


```

constはクラス定数を定義する際に用いる。
クラス定数は定義したクラスの初期化時に用いられる設定のフラグやオプションに用いられるもので、要はデフォルトの値だと思えばいい。
アクセスするにはクラス名::定数名。


## ここまでのまとめ

```php:メソッドとアクセス修飾子他

```php:メソッドで使う場合

<?php

	
	class Employee {

		(public)private static $company = "出版社"; // 1,4

		public static function getCompany { // 2

			return self::$company;
		}

		public static function setCompany($value) { // 3

			self::$company = $value;
		}


	}


 ?>


```

メソッドも変数などと同じようにアクセス修飾子を用いることができる。
まず1は`public static $company`となっていて`public`がついているのと合わせてインタンス化せずとも外部から呼び出すことができるようになっている。
2も同じく`static`なのでインスタンス化せずとも外部から呼び出せる。ここでは`$compan`yを返す処理が定義されている。
3も以下略で処理は`$company`に値（この場合は社名などだろう）を代入するという処理になっている。
つまり、この段階で`$company`は外部から直接アクセスせずとも、実質アクセスできるような状態になっている。
すると不用意に外部から直接アクセスできるような状態にしておくのは望ましくないので、4でアクセス修飾子が`public`から`private`に変わるというのが上のコードの顛末ということになる。
なお、`static`が記載されている場合、メソッドで`$this`は用いることはできない。


## コンストラクタとデストラクタ

```php:コンストラクタとデストラクタの基本

<?php 


    class Employee {

        const PARTTIME = 0x01;
        const REGULAR = 0x02;
        const CONTRACT = 0x04;

        private $name;
        private $type;

        public function __construct($name,$type) {

            $this->name = $name;
            $this->type = $type;
        }

    }

    $yamada = new Employee("山田",Employee::REGULAR);
    
    var_dump($yamada);


 ?>

```

```php:var_dumpの実行結果

object(Employee)#1 (2) {
  ["name":"Employee":private]=>
  string(6) "山田"
  ["type":"Employee":private]=>
  int(2)
}


```
コンストラクタとデストラクタはクラスのインスタンスの作成・削除のタイミングで呼び出されるメソッド。
前者がインスタンスの作成をキーに実行されるメソッド、後者が削除をキーに実行されるメソッド。
実際はマジックメソッドと呼ばれる、PHPに備え付けられているメソッドのうちの1つなのだが詳しくは別項にて。

 コンストラクタはインスタンスを宣言しオブジェクトを生成する際に必要なパラメータやそのクラスのオプションなどを引数と一緒に受け取り、プロパティにセットする。
 例えば上記の例、まずクラス定数と変数を定義する。
 次に`public`でコンストラクタメソッドを定義する。このとき引数に先に定義した2つの変数を指定する。
 ついでに中は`$this`を用いてクラスの変数にアクセスできるようにしておく。
 最後はインスタンス宣言、今回のポイントはここで引数を`("山田",Employee::REGULAR)`と指定すること。
 逆算していくと、`$name`はコンストラクタメソッドにより`$this->name = $name;`となっているので、わざわざ`$yamda->name = "山田";`とわざわざ書かなくてもいいことになる。
 また第2引数に$typeが指定されているので、そこにクラス定数である`Employee::REGULAR`が代入される。
結果上記のような実行結果となる。
 ちなみにここまでの処理をみればわかるが、今回のプロパティはコンストラクタメソッドにより外部から間接的にアクセスできるので、アクセス修飾子はprivateにするのが適切である。

 デストラクタについてはPHP5.6.4以降より明示的に記述する必要はないので役割だけ覚えておこう。



## 実践してみる

```php:今回のまとめとおさらい1

 <?php 

 // 閑話休題 オブジェクト指向基本のおさらい

 class Robot {

 	private $name = "";
 	public function setName ($name) {
 		$this->name = (string)filter_var($name);

 	}

 	public function getName () {
 		return $this->name;
 	}
 }

 $a = new Robot();
 $a->setName('アトム');
 $b = new Robot( );
 $b->setName('プルート');

 echo $a->getName(); // アトム
 echo $b->getName(); // プルート

  ?>
  <!-- 外部には機能的にまとめられた最低限必要な情報しか公開しない。 -->

 

```

```php:その2

 <?php 

  class Robot {

  	private $name = "";
  	public function __construct ($name) {
  		$this->setName($name);
  	}

  	public function setName($name) {
  		$this->name = (string)filter_var($name);
  	}

  	public function getName () {
  		return $this->name;
  	}

}
  	$a = new Robot('アトム');
  	$b = new Robot('プルート');

  	echo $a->getName(); // アトム
  	echo $b->getName(); // プルート


 
```

参考
 
パーフェクトPHP
[PHPオブジェクト指向入門（前半）](https://qiita.com/mpyw/items/41230bec5c02142ae691#1-2)
[ts0818のブログ：PHPで擬似変数$thisって何のためにあるのか？](https://ts0818.hatenablog.com/entry/2015/10/03/215418)
[わわわIT用語辞典 ](https://wa3.i-3-i.info/word11858.html)