見出し画像

PHPのオブジェクト指向構文を学んだ

業務でLaravelを使っているのですが、PHP自体の勉強ってちゃんとしたことなかったなぁと思い「独習PHP」を参考にオブジェクト指向構文を学びました。

基本のクラスの書き方

<?php
class Person {
   public $firstName;
   public $lastName;
   // コンストラクタ
   public function __construct(string $firstName, string $lastName) {
       $this->firstName = $firstName;
       $this->lastName = $lastName;
   }
   // デストラクタ
   public function __destruct() {
       print __CLASS__ . "オブジェクトが破棄されました \n";
   }
   public function show() {
       print "ボクの名前は{$this->lastName}{$this->firstName}です \n";
   }
};

Javascriptではデストラクタがない・・?(多分)ので、オブジェクトが破棄されるタイミングで実行されるメソッドがあることにびっくりしました。

<?php
require_once 'person.php';
$p = new Person('太郎', '山田');
$p->show(); // ボクの名前は山田太郎です Personオブジェクトが破棄されました

静的メソッド

インスタンスを生成しなくてもクラスから直接呼び出せるメソッドのこと。

下記の例で書いているfloatは浮動小数点のこと。整数のint(1.414213 )とは違って、「3.548E5」のような指数表外縁を使える。

<?php
class Area {
   public static $pi = 3.14;

   public static function circle(float $radius): float {
       return pow($radius, 2) * self::$pi;
   }
};

ちなみに、静的メソッドの中では$thisキーワードは使えないので、「self::」を使います。(クラスの定数でconst PI = 3.14 , self::PI って書き方もできる)

<?php
require_once 'area.php';
print '円の面積: '. Area::circle(10) . 'cm^2'; // 円の面積: 314cm^2

カプセル化

使い手に必要ない情報を隠す(ブラックボックス化)すること。

アクセス修飾子
・public → どこからでもアクセスできる
・protected → 現在のクラスとサブクラスでのみアクセスできる
・private → 現在のクラスの中でのみアクセスできる

(protectedが馴染みない。どんなときに使うんだろう・・?)

カプセル化のメリットとして、下記のような三角形の面積を求めるTriangleFigureクラスを例に考えていきます。

getAreaメソッドは $baseや$heightが負の値・文字列でもPHPは実行されてしまいます・・。

<?php
class TriangleFigure {
   public $base;
   public $height;
   // 初期化
   public function __construct() {
       $this->base = 1;
       $this->height = 1;
   }
   // 面積を取得
   public function getArea(): float {
       return $this->base * $this->height / 2;
   }
}

このように負数や文字列を指定しても、エラーすら出ず「0」という結果が返ってきます・・。

<?php
require_once 'TriangleFigure.php';
$tri = new TriangleFigure();
$tri->base = -10; // 負数
$tri->height = 'Moji'; // 文字列
print "三角形の面積:{$tri->getArea()}"; // 三角形の面積:0

アクセサメソッド

その問題を解決するには、$baseと$heightプロパティはprivateにして外から読み書きできなくします。

値をセットしたいときはセッターを経由すれば、変な値が入れられたときも無視できるし、(ここには書いてないけど)エラーを出すこともできます。

<?php
class TriangleFigure {
   private $base;
   private $height;
  ...中略

   // baseのゲッター・セッター
   public function getBase(): float {
       return $this->base;
   }
   public function setBase(float $base) {
       if($base > 0) {
           $this->base = $base;
       }
   }
   // heightのゲッター・セッター
   public function getHeight():float {
       return $this->height;
   }
   public function setHeight(float $height) {
       if($height > 0) {
           $this->height = $height;
       }
   }
  ...中略
}

継承

継承するときはextendsをclass名に付けます。上書きしたいときはparent:: と書いて今回はmiddleNameを追加しています。

<?php
require_once 'person.php';
class Foreigner extends Person {
   public $middleName;
  // コンストラクタ
   public function __construct(string $firstName, string $middleName, string $lastName) {
       parent::__construct($firstName, $lastName);
       $this->middleName = $middleName;
   }
   public function show() {
       print "ボクの名前は{$this->lastName}{$this->middleName}{$this->firstName}です \n";
   }
}
$f = new Foreigner('太郎','クリス', '山田');
$f->show(); // ボクの名前は山田クリス太郎です

最後に

ここまでで基本的なクラスの定義、カプセル化、継承を学習しました。

ポリモーフィズム・トレイト・・などまだ分からないことがあるので時間見つけて、続きやっていこうと思います。

独習PHPすごく分かりやすくて、買ってよかった・・。

勉強用リポジトリ

これと似たようなRuby版・Javascript版の学習を下記リポジトリでしました。

Ruby

Javascript

自分が触ったことのあるのがスクリプト言語ばっかなので、今度はコンパイラ言語を勉強してみたいなぁ。

これ買ってJavaやろうかな。


スキ頂けると嬉しいです〜