クラスとは何か
クラスの基本的な役割
プログラミングを学び始めると、最初は変数や配列、関数を中心にコードを書くことが多いでしょう。
しかし、アプリケーションが複雑になるにつれて「データ」と「処理」をうまく整理する必要が出てきます。
ここで登場するのが「クラス」と呼ばれる仕組みです。クラスとは、オブジェクト指向プログラミング(OOP)の中心的な要素であり、データとそれに関連する処理をひとまとまりにして扱える構造です。
クラスは「設計図」に例えられることがよくあります。例えば「車」というクラスを定義すれば、車が持つべき属性(色、速度、燃料量など)や機能(走る、止まる、曲がるなど)をまとめて記述できます。
そして、その設計図から実際に「車のオブジェクト」を作り出す工程をインスタンス化といいます。一つの同じクラスから、「赤い車」と「青い車」という別々のインスタンスを作り、それぞれに独立したデータを保持させることができます。
このように、クラスは共通の枠組みを提供しつつ、個別に独立したデータや状態を持つインスタンスを生成するための土台となります。
オブジェクト思考の考え方
オブジェクト指向の考え方には大きく3つの柱があります。
第一は「カプセル化」です。これはデータと処理をひとつのクラスにまとめ、外部から直接触れられないように制御する仕組みを指します。これにより、内部の実装を隠しつつ必要な部分だけを公開でき、予期せぬ不具合を防ぎます。
第二は「継承」で、既存のクラスをもとに新しいクラスを定義し、共通の機能を再利用できる仕組みです。例えば「車クラス」を継承して「スポーツカー」や「トラック」のクラスを作れば、それぞれが車の性質を持ちつつ独自の特徴を追加できます。
第三は「ポリモーフィズム(多態性)」で、同じメソッド名でありながらクラスごとに異なる振る舞いを持たせられる点です。これにより、同じインターフェースを使って異なる種類のオブジェクトを扱えるようになります。
これらの概念を踏まえると、クラスの基本的な役割は「現実世界の概念をプログラム上で再現し、秩序立てて管理すること」と言えます。クラスを導入することでコードの見通しが良くなり、再利用性や保守性が飛躍的に高まります。
小規模なスクリプトでは手続き型の書き方でも問題ありませんが、中規模以上のプロジェクトではクラスを使うことで設計の自由度が広がり、長期的に安定した開発が可能となるのです。
クラスを定義する方法
PHPでクラスを定義する際には、class
キーワードを使います。基本的な書き方は非常にシンプルで、次のようになります。
class クラス名 {
// プロパティ(変数)
// メソッド(関数)
}
ここで「クラス名」は任意の名前を付けられますが、一般的には先頭を大文字にし、意味の分かる英単語を用いるのが慣習です。
クラスの中には、データを保持する「プロパティ」と、処理を定義する「メソッド」を記述できます。プロパティは変数のようなもので、オブジェクトごとに異なる値を持ちます。メソッドは関数と同じ書き方ですが、クラスの中に属するため、クラスに紐づいた処理を記述できます。
class Car {
public $color;
public function drive() {
echo "車が走ります";
}
}
この例では「Car」というクラスを定義し、$color
というプロパティと drive()
というメソッドを持たせています。
ここで使われている public
は可視性を示す修飾子で、外部からアクセスできることを意味します。他にも private
や protected
があり、アクセス範囲を制御できます。
このようにクラスを定義することで、現実世界の「モノ」や「概念」をプログラムとして表現できるようになります。次のステップでは、このクラスから実際にオブジェクトを生成して使う方法を学びます。
クラスをインスタンス化する方法
クラスを定義しただけでは、まだ実際に使うことはできません。クラスはあくまで「設計図」であり、そこから「実体」を作り出す必要があります。その実体を インスタンス と呼び、インスタンスを生成する作業を インスタンス化 と言います。PHPでは、new
キーワードを用いることで簡単にインスタンスを作成できます。
例として、先ほどの Car
クラスを使ってみましょう。
class Car {
public $color;
public function drive() {
echo "車が走ります";
}
}
// インスタンス化
$myCar = new Car();
このコードでは、new Car()
によって Car
クラスのインスタンスを生成し、その参照を $myCar
に代入しています。これにより $myCar
は Car
クラスのオブジェクトとなり、プロパティやメソッドにアクセスできるようになります。
例えば、次のように利用できます。
$myCar->color = "赤";
echo $myCar->color; // 赤 と表示される
$myCar->drive(); // 「車が走ります」と表示される
このように、インスタンス化によってクラスの設計を実際のプログラム上で動かせるようになります。また、一つのクラスから複数のインスタンスを生成でき、それぞれが独立した状態を保持します。例えば $car1
は赤色、$car2
は青色というように、同じクラスから異なるオブジェクトを作ることが可能です。これがオブジェクト指向の大きな特徴であり、再利用性と拡張性を高める仕組みなのです。
クラスの構成要素
コンストラクタとは何か
クラスをインスタンス化した際に、自動的に呼び出される特別なメソッドを コンストラクタ と呼びます。
通常のメソッドは明示的に呼び出さないと実行されませんが、コンストラクタは new
キーワードでインスタンスを生成した瞬間に実行され、初期化処理を担当します。
PHPでは __construct
という名前のメソッドを定義することでコンストラクタを作ることができます。
class Car {
public $color;
public function __construct($color) {
$this->color = $color;
}
public function drive() {
echo "{$this->color}の車が走ります";
}
}
$car1 = new Car("赤");
$car2 = new Car("青");
$car1->drive(); // 赤の車が走ります
$car2->drive(); // 青の車が走ります
この例では、インスタンス化の際にコンストラクタへ色を引数として渡しています。コンストラクタはそれを $this->color
に代入し、オブジェクトの初期状態を設定します。
また、コンストラクタは省略可能です。もし定義しなければ、PHPが空のコンストラクタを自動的に用意するため、初期化処理が不要なクラスでは記述しなくても問題ありません。
ただし、実用的なクラスを作る際には、必要なデータを必ずコンストラクタで受け取るようにすると、コードの安全性と可読性が高まります。
クラス変数の定義と使い方
PHPにおける クラス変数 とは、インスタンスごとに異なる値を持つプロパティとは異なり、クラス自体に属する変数のことを指します。
すべてのインスタンスで共有されるため、クラス全体で共通の情報を管理したい場合に有効です。クラス変数を定義する際には、static
キーワードを用います。
基本的な書き方は次の通りです。
class Car {
public static $count = 0;
public function __construct() {
self::$count++;
}
}
ここでは Car
クラスに $count
というクラス変数を定義しました。コンストラクタ内で self::$count++
としているため、インスタンスが生成されるたびにカウントが増えます。このように、クラス変数は self::
を使ってアクセスします。インスタンスから直接呼び出すのではなく、クラス名を指定して呼び出すのが一般的です。
$car1 = new Car();
$car2 = new Car();
echo Car::$count; // 2 と表示される
この例では、2つのインスタンスを生成した結果、クラス変数 $count
の値は「2」となります。どのインスタンスからも同じ値を参照できることが分かります。
クラス変数は「全体で共通の状態」を表すのに便利ですが、使いすぎると依存関係が複雑になりやすいため注意が必要です。特に、インスタンスごとに独立したデータが必要な場合は通常のプロパティを使うべきです。用途を明確に分けて活用することが、理解しやすく保守性の高いコードにつながります。
プロパティの定義とアクセス方法
プロパティとは、クラスが持つ「データ」を表す変数のことです。インスタンスごとに異なる値を保持できるため、オブジェクトの状態を管理する上で中心的な役割を果たします。
PHPでプロパティを定義する際には、変数の前にアクセス修飾子(public
、protected
、private
)を付けて宣言します。
class Car {
public $color;
private $speed;
}
ここでは $color
が外部からアクセス可能なプロパティ、$speed
がクラス内部でしか触れないプロパティです。アクセス修飾子によってプロパティの可視性が決まり、コードの安全性や設計方針に大きな影響を与えます。
public
は誰でもアクセス可能、protected
はクラス自身と継承先でのみアクセス可能、private
は定義したクラス内だけで利用できます。
プロパティへのアクセスは ->
演算子を使います。
$car = new Car();
$car->color = "赤"; // プロパティに値を代入
echo $car->color; // 赤 と表示される
一方で private
の $speed
は直接アクセスできません。その場合はゲッターやセッターと呼ばれるメソッドを用意し、必要に応じて値を取得・変更するのが一般的です。
class Car {
private $speed;
public function setSpeed($speed) {
$this->speed = $speed;
}
public function getSpeed() {
return $this->speed;
}
}
$car = new Car();
$car->setSpeed(100);
echo $car->getSpeed(); // 100
このようにプロパティを定義し、適切なアクセス方法を設計することで、データの一貫性を保ちながら安全にオブジェクトを扱うことができます。
メソッドの定義と呼び出し方
クラスにおける メソッド とは、そのクラスに紐づく関数のことです。プロパティがデータを表すのに対し、メソッドは「そのデータを操作する処理」を表します。メソッドを定義することで、オブジェクトの動作や振る舞いを実装できます。
定義の際は関数と同じく function
キーワードを使い、必要に応じてアクセス修飾子(public
、protected
、private
)を付けます。
class Car {
public $color;
public function drive() {
echo "{$this->color}の車が走ります";
}
}
この例では drive()
というメソッドを定義しています。メソッド内で $this->color
を使っている点に注目してください。$this
は「現在のインスタンス自身」を指す特殊な変数で、インスタンスのプロパティや他のメソッドにアクセスするために用います。
呼び出し方はシンプルで、インスタンス化したオブジェクトに対して ->
演算子を使います。
$car = new Car();
$car->color = "青";
$car->drive(); // 青の車が走ります
また、メソッドには引数を渡すこともできます。
class Calculator {
public function add($a, $b) {
return $a + $b;
}
}
$calc = new Calculator();
echo $calc->add(3, 5); // 8
このようにメソッドを定義することで、クラスに「機能」を持たせることができます。アクセス修飾子を適切に使い分ければ、外部に公開する処理と内部のみに閉じる処理を整理でき、保守性の高い設計が可能になります。
実践的なクラス設計
値オブジェクトの作成例
オブジェクト指向プログラミングでよく登場する設計パターンのひとつに 値オブジェクト(Value Object) があります。値オブジェクトとは、その名の通り「値そのものを表すオブジェクト」です。単なる数値や文字列では表現しきれない意味を持たせたいときや、値の不整合を防ぎたいときに有効です。
例えば、ユーザーのメールアドレスを扱うケースを考えてみましょう。単純に文字列として $email = "test@example.com";
としてしまうと、誤って不正な文字列("aaaa"
など)を代入してしまう可能性があります。しかし、値オブジェクトとしてクラス化すれば、値を生成するときに必ずバリデーションを行い、常に正しい値が保持されるようにできます。
メールアドレスの値オブジェクト例
class Email {
private $value;
public function __construct(string $value) {
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException("不正なメールアドレスです: {$value}");
}
$this->value = $value;
}
public function getValue(): string {
return $this->value;
}
}
この Email
クラスは、インスタンス化の際に必ずバリデーションを通すため、不正な値を保持できません。使い方は以下のようになります。
try {
$email = new Email("user@example.com");
echo $email->getValue(); // user@example.com
} catch (InvalidArgumentException $e) {
echo $e->getMessage();
}
誤った形式の文字列を渡せば例外が発生し、安全にシステムを守ることができます。
値オブジェクトを使うメリット
- 不変性
値オブジェクトは基本的に変更不可(immutable)として設計します。生成されたら中身は変わらないため、予期せぬ副作用を避けられます。 - 型安全性
ただの文字列や数値ではなく「Email型」「Money型」「PhoneNumber型」などを導入することで、コードの意図が明確になり、誤用を防げます。 - ビジネスルールの集約
バリデーションやフォーマットなどのルールをクラスに閉じ込められるため、再利用性が高まり、他の部分で同じ処理を繰り返し書く必要がなくなります。
値オブジェクトは、小規模なコードでは少し冗長に見えるかもしれません。しかし、中規模以上のアプリケーションでは「意味のある値」を表現し、データの正当性を保証する強力な手段となります。日常的に使うデータ型に意味づけを与えるために、ぜひ値オブジェクトを取り入れてみてください。