🕛 2024.5.17 07:32

【実践】Hands-On で理解するオブジェクト指向プログラミング(OOP) クラスとオブジェクトの基本

  • クラスとオブジェクトの基本的な違いや、それぞれがどのように動作するのかわからない
  • クラスとオブジェクトの実装方法がわからない
  • 実際にクラスとオブジェクトを書こうと思っても書けない

プログラマー歴20年の管理人が、これらの悩みを解決できるように、手を動かしながらOOPのオブジェクトとクラスの基本を学べるように記事を書きました!

この記事を読むことで、オブジェクト指向プログラミング(OOP)の基本概念を理解し、クラスとオブジェクトの実装方法を学ぶことができます!

  • オブジェクト指向の基本概念を理解できる:オブジェクトとクラスの基本的な概念を明確にします。
  • クラスとオブジェクトの実装方法がわかる:プロパティとメソッドの追加、コンストラクタの実装方法を具体的なコード例で学習していきます。

この記事を読み終えた後、このコードを理解し、実践的なスキルが身についているはずです。

<?php
class Car {
    // プロパティの定義
    public $color;
    public $model;
    public $year;

    // コンストラクタの定義
    public function __construct($color, $model, $year) {
        $this->color = $color;
        $this->model = $model;
        $this->year = $year;
    }

    // メソッドの定義
    public function getDescription() {
        return "This car is a " . $this->color . " " . $this->model . " from " . $this->year . ".";
    }

    // 新しいメソッドの追加
    public function startEngine() {
        return "The " . $this->model . " engine has started.";
    }
}

// オブジェクトの作成
$myCar = new Car("blue", "Honda", 2020);
echo $myCar->getDescription(); // 出力: This car is a blue Honda from 2020.
?>

オブジェクト指向プログラミングの基本概念を理解し、クラスとオブジェクトの作成、プロパティとメソッドの追加、コンストラクタの実装などの基本的なスキルを習得できます。

それでは手を動かしながら、オブジェクト指向プログラミング(OOP)の基本概念であるオブジェクトとクラスの基本について解説します。

なぜオブジェクトとクラスを使うのか

理由1️⃣ コードの使い回しができる

理由2️⃣ コードがわかりやすくなる

理由3️⃣ 扱うでデータを保護できる

理由4️⃣ 似たコードを作りやすい

理由5️⃣ コードをいろんなかたちで使える

オブジェクトとクラスを使うと、コードが使いやすく、わかりやすく、安全に、そして簡単に拡張できるようになるメリットがあるからです。

オブジェクトとは?クラスとは?

クラスとは?

「車」のクラスを作成します。実際にコードを書いてみましょう。

<?php
class Car {

}
?>

クラスは設計図です。車の色やモデル、エンジンをかける機能を設計図に書きます。

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル

    //エンジンをかける機能
    public function startEngine() {
        return "The engine has started.";
    }
}
?>

車の色やモデルは「プロパティ」、エンジンをかける機能は「メソッド」と呼びます。エンジンをかけると「The engine has started.」と出てきます。

public は、オブジェクト指向プログラミングで使われる「アクセス修飾子」の一つです。これを使うことで、クラス内のプロパティやメソッドにどこからアクセスできるかを決めます。どこからでもアクセスできるよう指定しました。

オブジェクトとは?

次にオブジェクトを説明します。オブジェクトは、設計図(クラス)をもとに作った実際のものです。これをインスタンスと呼びます。

設計図(クラス)から実際の車(オブジェクト)を作って、その車に色やモデルを設定して、エンジンをかける、というイメージです。

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル

    //エンジンをかける機能
    public function startEngine() {
        return "The engine has started.";
    }
}

// Carクラスから車の色やモデルを決める
$myCar = new Car();
$myCar->color = "red";
$myCar->model = "Toyota";

// エンジンをかける
echo $myCar->startEngine(); // 出力: The engine has started.

?>

このコードを lesson_01.php と名前をつけてファイルに保存しましょう。
実行してみます。

$ php lesson1.php 
The engine has started.

「The engine has started.」が表示されたということは、車のエンジンがかかりましたね。ここは空想が必要です 😀

https://miro.medium.com/v2/resize:fit:1400/0*VSdGN-ncx38ddttn

コンストラクタを実装する

次にクラスの重要な要素コンストラクタを実装してみましょう

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル

    // コンストラクタの実装
    public function __construct($color, $model) {
        $this->color = $color;
        $this->model = $model;
    }

    //エンジンをかける機能
    public function startEngine() {
        return "The " . $this->model . " engine has started.";
    }
}

// オブジェクトを作成
$myCar = new Car("blue", "Honda");

// オブジェクトの機能を実行
echo $myCar->startEngine(); // 出力: The Honda engine has started.
?>
$ php lesson1.php 
The Honda engine has started.

「The Honda engine has started.」と、どのモデルの車がエンジンスタートしたのかわかるようになりました。

コンストラクタとは?

オブジェクトを作るときに最初に呼ばれる特別な関数です。新しいオブジェクトができたら、コンストラクタが自動的に動きます。そして、オブジェクトの初期設定や必要なデータを設定することができます。

コンストラクタを使うことでオブジェクト作成時に、車の色とモデルを設定することができました。次のようなメリットが生まれました。

  • コードの簡素化
    • オブジェクト生成時に必要な処理をまとめることで、コードがより読みやすく、簡潔になります。
  • オブジェクトの状態保証
    • オブジェクトが常に適切な状態で生成されることを保証できます。オブジェクトが動作するために必要なプロパティに、適切な値がきちんと設定されてします。また、モデルのところに色が設定されていないなどプロパティに矛盾がないです。
  • コードの再利用性
    • よく使用する初期化処理をコンストラクタにまとめることで、他のクラスでも同じコンストラクタを再利用しやすくなります。

プロパティとメソッドを追加しましょう

プロパティ、メソッドとコンストラクタとはなにか理解したので、それぞれコードに追加しましょう!

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル
    public $year;  //車の製造年

    // コンストラクタの実装
    public function __construct($color, $model, $year) {
        $this->color = $color;
        $this->model = $model;
        $this->year = $year;
    }

    // 車の説明をするメソッド
    public function getDescription() {
        return "This car is a " . $this->color . " " . $this->model . " from " . $this->year . ".";
    }

    // エンジンをかけるメソッド
    public function startEngine() {
        return "The " . $this->model . " engine has started.";
    }

}

// オブジェクトを作成
$myCar = new Car("blue", "Honda", 2022);

// オブジェクトの機能を追加
echo $myCar->getDescription();  // 出力: This car is a red Toyota.
echo $myCar->startEngine(); // 出力: The Honda engine has started.
?>
$ php lesson1.php 
This car is a blue Honda from 2022.The Honda engine has started.

車の製造年プロパティと車の説明をするメソッドを追加しました。オブジェクトを作成する時に、車の年代も自動的にコンストラクタが設定するようにしました。

データの隠蔽

データの隠蔽は、オブジェクト指向プログラミングの重要な概念の一つです。クラスの内部データを外部から隠すことで、データの一貫性を保ち、クラスの使用方法をより安全で明確にします。

データの隠蔽をするためには、セッターメソッドとゲッターメソッドを用います。

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル
    public $year;  //車の製造年

    // コンストラクタの実装
    public function __construct($color, $model, $year) {
        $this->color = $color;
        $this->model = $model;
        $this->year = $year;
    }

    // 車の説明をするメソッド
    public function getDescription() {
        return "This car is a " . $this->color . " " . $this->model . " from " . $this->year . ".";
    }

    // エンジンをかけるメソッド
    public function startEngine() {
        return "The " . $this->model . " engine has started.";
    }

   // ゲッターメソッド
    public function getColor() {
        return $this->color;
    }

    public function getModel() {
        return $this->model;
    }

    // セッターメソッド
    public function setColor($color) {
        $this->color = $color;
    }

    public function setModel($model) {
        $this->model = $model;
    }

}

// オブジェクトを作成
$myCar = new Car("blue", "Honda", 2022);

// ゲッターメソッドを使用してプロパティの値を取得
echo $myCar->getColor();  // 出力: blue
echo $myCar->getModel();  // 出力: Honda

// セッターメソッドを使用してプロパティの値を変更
$myCar->setColor("red");
$myCar->setModel("Toyota");

// オブジェクトの機能を追加
echo $myCar->getDescription();  // 出力: This car is a red Toyota.
echo $myCar->startEngine(); // 出力: The Honda engine has started.
?>

ゲッターメソッド(Getter Method)

ゲッターメソッドは、プロパティの値を取得するためのメソッドです。クラスの内部データを外部から直接アクセスするのではなく、ゲッターメソッドを通じてアクセスすることで、データの取得方法を制御できます。

ここでは車の色とモデルを取得しています。

セッターメソッド(Setter Method)

セッターメソッドは、プロパティの値を設定するためのメソッドです。プロパティの値を直接変更するのではなく、セッターメソッドを通じて変更することで、入力値の検証や追加の処理を行えます。

ここでは車の色とモデルを設定しています。

なぜデータの隠蔽をするのか

なぜゲッターメソッドとセッターメソッドを使ってデータを隠すのでしょうか。

データを隠蔽することでデータへのアクセスを制御することで、次のようなデメリットを回避するためです。

  • 予期しないバグが発生しやすくなる。
  • データの一貫性が保てず、システムの信頼性が低下する。
  • コードのメンテナンスが難しくなる。
  • クラスの再利用が難しくなり、コードの重複や不整合が増える。

次のようにセッターメソッドにバリデーションを加えることによってこれらのデメリットを解消できます。製造年のゲッターメソッドとセッターメソッドも追加します。

これにより、製造年が不適切な値にならないようにします。車の製造年にバリデーションを追加し、セッターメソッドで製造年の範囲をチェックするようにします。

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル
    public $year;  //車の製造年

    // コンストラクタの実装
    public function __construct($color, $model, $year) {
        $this->color = $color;
        $this->model = $model;
        $this->year = $year;
    }

    // 車の説明をするメソッド
    public function getDescription() {
        return "This car is a " . $this->color . " " . $this->model . " from " . $this->year . ".";
    }

    // エンジンをかけるメソッド
    public function startEngine() {
        return "The " . $this->model . " engine has started.";
    }

   // ゲッターメソッド
    public function getColor() {
        return $this->color;
    }

    public function getModel() {
        return $this->model;
    }

    public function getYear() {
        return $this->year;
    }

    // セッターメソッド
    public function setColor($color) {
        $this->color = $color;
    }

    public function setModel($model) {
        $this->model = $model;
    }

    public function setYear($year) {
        $currentYear = date("Y");
        if (is_int($year) && $year > 1885 && $year <= $currentYear) { // 自動車が発明されたのは1886年
            $this->year = $year;
        } else {
            throw new Exception("Invalid year value. Year must be between 1886 and the current year.");
        }
    }
}

// オブジェクトを作成
$myCar = new Car("blue", "Honda", 2022);

// ゲッターメソッドを使用してプロパティの値を取得
echo $myCar->getColor();  // 出力: blue
echo $myCar->getModel();  // 出力: Honda
echo $myCar->getYear() . "\n";   // 出力: 2022

// セッターメソッドを使用してプロパティの値を変更
$myCar->setColor("red");
$myCar->setModel("Toyota");
$myCar->setYear(2021);

// オブジェクトの機能を追加
echo $myCar->getDescription();  // 出力: This car is a red Toyota.
echo $myCar->startEngine(); // 出力: The Honda engine has started.

// 無効な年を設定して例外を確認
try {
    $myCar->setYear("二千二十二年"); // ここで例外が発生
} catch (Exception $e) {
    echo $e->getMessage() . "\n"; // "Invalid year value. Year must be between 1886 and the current year." と出力
}
?>

これで開発者が車の製造年に不正な値を入れた場合、バグが防げますし、数字だけしか入力できないデータの一貫性が保たれます。

またデータ毎にバリデーションをする必要がなく、セッターメソッドにバリデーションを設定するだけなのでメンテナンスが楽です。

まとめ

オブジェクト指向プログラミング(OOP)の基本を理解することで、コードの使い回しや保守性、再利用性を向上させることができます。

<?php
class Car {
    public $color; //車の色
    public $model; //車のモデル
    public $year;  //車の製造年

    // コンストラクタの実装
    public function __construct($color, $model, $year) {
        $this->color = $color;
        $this->model = $model;
        $this->year = $year;
    }

    // 車の説明をするメソッド
    public function getDescription() {
        return "This car is a " . $this->color . " " . $this->model . " from " . $this->year . ".";
    }

    // エンジンをかけるメソッド
    public function startEngine() {
        return "The " . $this->model . " engine has started.";
    }

   // ゲッターメソッド
    public function getColor() {
        return $this->color;
    }

    public function getModel() {
        return $this->model;
    }

    public function getYear() {
        return $this->year;
    }

    // セッターメソッド
    public function setColor($color) {
        $this->color = $color;
    }

    public function setModel($model) {
        $this->model = $model;
    }

    public function setYear($year) {
        $currentYear = date("Y");
        if (is_int($year) && $year > 1885 && $year <= $currentYear) { // 自動車が発明されたのは1886年
            $this->year = $year;
        } else {
            throw new Exception("Invalid year value. Year must be between 1886 and the current year.");
        }
    }
}

// オブジェクトを作成
$myCar = new Car("blue", "Honda", 2022);

// ゲッターメソッドを使用してプロパティの値を取得
echo $myCar->getColor();  // 出力: blue
echo $myCar->getModel();  // 出力: Honda
echo $myCar->getYear() . "\n";   // 出力: 2022

// セッターメソッドを使用してプロパティの値を変更
$myCar->setColor("red");
$myCar->setModel("Toyota");
$myCar->setYear(2021);

// オブジェクトの機能を追加
echo $myCar->getDescription();  // 出力: This car is a red Toyota.
echo $myCar->startEngine(); // 出力: The Honda engine has started.

// 無効な年を設定して例外を確認
try {
    $myCar->setYear("2022");
} catch (Exception $e) {
    echo $e->getMessage() . "\n";
}
?>

クラスとオブジェクトの基本概念からプロパティやメソッドの追加、コンストラクタの実装、データの隠蔽(エンカプシュレーション)までを学びました。

  1. コードの使い回し
    • クラスを定義することで、同じ設計をもとに複数のオブジェクトを作成し、コードを再利用できます。
  2. コードがわかりやすくなる
    • クラスとオブジェクトを使うことで、関連するデータと操作を一つにまとめ、コードの可読性が向上します。
  3. データの保護
    • ゲッターメソッドとセッターメソッドを使って、プロパティへのアクセスを制御し、データの一貫性を保つことができます。