PHPもオブジェクト指向型のプログラミングができるということで、classという概念がある。
classオブジェクトを使うことで似たような性質のものや、処理をまとめて使うことができるので覚えておきたい。
PHPのclassの宣言とインスタンス生成、使い方
PHPでもclass内で持たせる変数のことをプロパティとよび、class内に作成した関数をメソッドと呼ぶ。
class内にコンストラクタを定義することができ、classをnewで生成するタイミングで自動的に最初に実行される。つまりclassのインスタンス生成時の初期化処理を任せる形となる。
phpのコンストラクタの定義は必ず決まっていて __construct()で定義する。
以下事例。
<?php class Goblin { //プロパティ public $hp; public $mp; public $name; //コンストラクタ public function __construct($name) { $this->name = "ゴブリン" . $name; $this->hp = rand(1,20); $this->mp = rand(1,5); } //メソッド public function kougeki() { echo "{$this->name}は勇者を攻撃"; } }
これでGoblinクラスを定義できた。
クラスの宣言はclassと記述した後にクラス名を記述。先頭を大文字にすること。
クラスの内部にはプロパティ、コンストラクタ、メソッドを書く。
プロパティの宣言はpublicに続いて$で変数を指定する。
コンストラクタはメソッドと同じなのでfunctionで宣言し、決まって __construct()として宣言する。
このコンストラクタの中で、引数を受け取ってプロパティに値をセットするようにする。
$thisというのはこのクラスのインスタンスを生成したときの自分自身のことを指している。$this->nameとすることで自分自身のプロパティにアクセスすることができる。プロパティ名のほうには$マークはつけない。
また$thisに引き続いて->という矢印を使う事。他のプログラミング言語のように「.」ドットではないのが特徴。
メソッドは関数の宣言と同様に記述できる。
classのインスタンスの生成や、プロパティへのアクセス、メソッドの起動は以下のように行う。
$gob1 = new Goblin("A"); echo $gob1->name; echo "<br>"; echo $gob1->hp; echo "<br>"; echo $gob1->mp; echo "<br>"; echo $gob1->kougeki(); echo "<br>"; ?>
<表示結果>
クラスのインスタンスを生成するときは、
$gob1 = new Goblin(“A”);
のように、イコールの後にnewをつけて、クラス名と引数を渡すことで生成できる。
生成したインスタンスのプロパティやメソッドへのアクセスには->の矢印を使ってアクセスできるようになる。
変数やメソッドの前につけるpublicについて。
publilcの他に、privateとprotectedが使える。
privateはそのクラス内でしかアクセスできない挙動になる。もし上の例で$nameや、$hpや、$mpをprivateで指定した場合は、$gob->nameや、$gob->hpや、$gob->mpはエラーになる。
Fatal error: Uncaught Error: Cannot access private property Goblin::$mp
protectedで指定したプロパティに関しては、そのクラスの親子関係があるクラスであればアクセスできる。
PHPの親クラス、子クラスと継承
PHPのclassにも親クラス、子クラスという概念がある。
以下事例。
<?php class Slime { //プロパティ public $hp; public $mp; public $name; //コンストラクタ public function __construct($name) { $this->name = $name; $this->hp = rand(1,20); $this->mp = rand(1,5); } //メソッド public function kougeki() { echo "{$this->name}は勇者を攻撃"; } public function nigeru() { echo "{$this->name}は逃げ出した"; } } $slime1 = new Slime("スライム"); echo $slime1->kougeki(); echo "<br>"; echo $slime1->nigeru(); echo "<br>";
ここまでが普通のスライムに関する定義と、インスタンス生成とメソッドの実行をやってみた事例。
表示結果
次に、このスライムクラスを継承してホイミスライムを作ってみる。
class HoimiSlime extends Slime { public function hoimi() { echo "{$this->name}はホイミを使った"; } //親クラスのメソッドを上書き(オーバーライド) public function nigeru() { echo "{$this->name}は飛んで逃げた"; } } $hslime1 = new HoimiSlime("ホイミスライム"); echo $hslime1->kougeki(); echo "<br>"; echo $hslime1->hoimi(); echo "<br>"; echo $hslime1->nigeru(); echo "<br>"; ?>
これで既にあるクラスを継承することができた。
継承元を親クラス、継承した側を子クラスと呼ぶ。
親クラスを継承するには、子クラスの宣言のところで
extends 親クラス
として宣言してあげればよい。
子クラスの中には新たにプロパティやメソッドを追加することができる。
上の例ではスライムを継承したホイミスライムでは、ホイミが使えるようにメソッドhoimi()を実装している。
またnigeru()メソッドを上書きして飛んで逃げる仕様にした。
PHPのクラスにも親クラスのメソッドの上書き(オーバーライド)処理ができるようになっている。
表示結果
PHPのstaticメソッド、staticプロパティ
これはクラスのインスタンスを生成していなくてもアクセスできるメソッドやプロパティ。
以下事例。
Goblinクラスに、staticで$wamei(和名)というプロパティと、$numといって何匹目のインスタンスが生成されたかをカウント保持しておくプロパティを持たせた。
それからstaticなメソッドとしてsetumei()というメソッドを実装した。
<?php class Goblin { //プロパティ public $name; public static $wamei = "小鬼"; public static $num = 0; //コンストラクタ public function __construct() { self::$num++; $this->name = "ゴブリン" . self::$num; } //staticメソッド public static function setumei() { echo "ゴブリンは最弱のモンスター"; } }
コンストラクタのところでself::$num++とやって生成されたインスタンス数をカウントするとともに、nameにゴブリン0, 1, 2, 3, …となるように名前を変えている。
気を付けたいのは同じクラス内でstaticなプロパティにアクセスするには、self::$numとやる必要がある。
$thisじゃなくてself::を使う。$thisとselfと混同しないように整理しておこう。
ちなみに$this->numとやるとプログラムが期待した通りに動かなかった。staticなプロパティやメソッドにアクセスするときは::を使う、と覚えておこう。
$thisは自分自身という意味で、インスタンスが生成されたオブジェクト内で使われる、ということになると理解。
statiなメソッドやプロパティを実行するには以下のようにする。
クラス名::プロパティ
クラス名::メソッド
として実行できる。
Goblinクラスのインスタンスを生成しなくても、staticがついたメソッドsetumei()を実行することができる。同様にstaticなプロパティもGoblin::$wameiとしてアクセスできる。
Goblin::setumei(); echo "<br>"; echo Goblin::$wamei; echo "<br>";
表示結果
ではGoblinクラスのインスタンスを2つ生成してnameを表示してみる。
$gob1 = new Goblin(); echo $gob1->name; echo "<br>"; $gob2 = new Goblin(); echo $gob2->name; echo "<br>"; ?>
表示結果
ちゃんとnumがインクリメントされてカウントしつつ、nameに反映されることを確認できた。
PHPの抽象クラスabstract
abstractを使うことで抽象クラスを宣言できる。
抽象クラス内ではabstractで宣言されたメソッドは中身を記述しない。子クラスで再定義する必要がある。
抽象クラスはインスタンスを生成できないので、抽象クラスを継承したクラスを作成してインスタンスを生成していく。
事例
<?php abstract class Human { public $name; abstract public function hanasu(); //子クラスで必ず実装させるために、中身を実装しない } //abstractクラス内で宣言したabstractメソッドは中身を実装せず、子クラスで再定義する必要がある //Humanクラスを継承したYusyaクラスを宣言 class Yusya extends Human { public function hanasu() { echo "私は勇者です"; } } //Humanクラスを継承したMahoクラスを宣言 class Maho extends Human { public function hanasu() { echo "私は魔法使いです"; } } //クラスのインスタンスを生成してメソッドを実行してみる $u = new Yusya(); $u->hanasu(); echo "<br>"; $m = new Maho(); $m->hanasu(); ?>
表示結果
PHPのインターフェイスの使い方
interfaceというキーワードを使ってクラスと同じように宣言できる。インターフェイスはクラスと同じように宣言できるが、メソッドの中身は書かない
interface内のメソッドは必ず「public」を指定する必要がある。
interfaceを継承するには、implements(実装)を使う。extends(継承)と違い複数継承できる。
事例
<?php //剣士インターフェイス interface Kensi { public function tatakau(); } //魔法使いインターフェイス interface MahouTukai { public function jumon(); } //魔法剣士クラスを定義する、KensiとMahouTukaiを継承して実装する class MahouKensi implements Kensi, MahouTukai { public function tatakau() { echo "剣で戦う"; } public function jumon() { echo "魔法を使う"; } } $mk = new MahouKensi(); $mk->tatakau(); echo "<br>"; $mk->jumon(); ?>
2つのinterfaceを継承した、MahouKensiのインスタンスを生成して、再定義したtatakau()と、jumon()を実行してみた。
表示結果