前回は、関数編後編として、自分で関数を作る方法を解説した。
また、ファイルを別にし、それを読み込むrequire、require_once関数も扱った。
複数ファイルで使用する共通部品を外に分けておく考え方は非常に重要なので、是非覚えておいて欲しい。
前回の記事は以下だ。
【PHP講座09】自分で関数を作ってみよう | Shino’s Mind Archive
さて、今回はクラスとオブジェクトというものを扱う。
簡単に考え方だけ書いてしまうと、互いに関係する変数や処理をまとめてしまおう、というものだ。
ちょっと話が複雑になってくるので、一個一個確実に進めていこう。
クラス、オブジェクトとは
ある程度大きなプログラムになると、どの変数やユーザー定義関数が何を表しているのか、分かりづらくなってくる。
特に、ある一つのモノを表現するために複数の変数を使わなければいけない場合がある。
例えば、店に売られている商品。
説明のために簡略化するが、最低でも以下の情報は欲しいだろう。
- 商品名
- 値段
- 在庫数
その他、食品であれば賞味期限、本であれば作者や出版社などなど、必要な情報は多量にある。
これを別々の変数で管理していると、どの変数が何を表していたっけ?という状態になってしまう。
また、共通する処理として売れたら在庫数を減らす、入荷したら在庫数を増やすといった処理も考えられる。
これも、別々の関数として定義しているとこれまた分からなくなってしまう。
こういった問題を解決するのが、今回解説するクラスという考え方だ。
冒頭にもちらっと書いたが、クラスは互いに関係する変数や処理をまとめようという考え方だ。
ある一つの商品という枠があり、その中に商品名や値段などの情報と、売れた時や入荷した時などの処理が定義されているようなイメージだ。
そして、その枠を使って、実際にデータを作る。
この、枠のことをクラス、作られたデータのことをオブジェクトと呼ぶ。
クラスの定義方法
では、まずはクラスから書き方を見ていこう。
class クラス名 {
// 変数
// 関数
}
このように、class クラス名
でその枠の名前をつける。
その後ろの中括弧内に、枠の中身を定義していくのだ。
この、クラスに定義する変数や関数には特別な名前が付けられている。
クラスに定義する変数のことをプロパティ、関数のことをメソッドと呼ぶので覚えておこう。
では、それぞれの書き方を。
まず、プロパティからだ。
アクセス修飾子 プロパティ名;
これを書くことで、クラスに持たせる変数を定義できる。
アクセス修飾子とは、そのプロパティにどこからアクセスできるかを表すもので、以下3つがある。
アクセス修飾子 | 意味 |
---|---|
public | どこからでもアクセス可能 |
protected | クラス内部と継承先からのみアクセス可能 |
private | クラス内部からのみアクセス可能 |
protectedの意味に継承先と書いてあるが、この詳細は次回解説するので、一旦は無視してもらっても構わない。
簡単に書くと、publicとつけたらどこでもそのプロパティにアクセスできるが、privateとつけたらそのクラス内のメソッドからしかアクセスできなくなる。
基本的には、可能な限り狭い範囲で定義するようにしよう。
そして、プロパティ名は通常の変数と同じく、先頭に$をつける。
具体例は、メソッドの説明が終わった後にお見せしよう。
では、そのメソッドの説明だ。
定義方法は以下の通り。
アクセス修飾子 function メソッド名(引数){
// 処理内容
}
通常のユーザー定義関数の定義方法に、アクセス修飾子が追加された形だ。
このアクセス修飾子は、上に解説したプロパティにつけるものと同じ。
こちらも、できる限り狭い範囲に留めておこう。
さて、このメソッドの中でプロパティにアクセスするとき、通常の変数と書き方が異なる。
メソッドから自身のプロパティにアクセスするときは、以下のように書く。
$this->プロパティ名
$this
というのは自身を表しており、その中の特定のプロパティ、という書き方をする。
このときに、プロパティ名の先頭に$は不要なので、それも気を付けよう。
この間を結んでいる->
をアロー演算子と呼び、ここ以外にも実際にオブジェクトを参照するときも使う。
また、自身に定義されている別のメソッドを呼ぶ場合も…
$this->メソッド名(引数);
このようにアロー演算子を使ってアクセスを行う。
これでメソッドを定義していくのだが、一つ特別なメソッドが存在する。
それが、コンストラクタというもの。
上に書いたが、クラスはあくまで枠であり、これを使ってオブジェクトを生成する。
その、オブジェクト生成時のみに呼び出される特殊なメソッドだ。
この書き方は以下の通り。
アクセス修飾子 __construct(引数){
// 処理
}
メソッド名が、__construct
というもので固定になる。
このアンダーバーは二つなので気を付けよう。
このように書くと、後述するオブジェクト生成時に一度だけ呼ばれ、その結果として生成されたオブジェクトを返すようになる。
ここでは、各プロパティの初期化など、最初にやっておきたいことを書くようにしよう。
ここまで色々と書いてきたので、それらを使う具体例をお見せしよう。
今回サンプルとして定義するのは、商品を表すクラスだ。
持つプロパティとメソッドは以下の通り。
- プロパティ
- 商品名
- 値段
- 在庫数
- メソッド
- (コンストラクタ)各プロパティに値をセットする
- 売れた時に在庫数を減らす
- 仕入れ時に在庫数を増やす
- 情報を表示する
これを実際に書いたものが以下だ。
<?php
class Product {
private $name;
private $price;
private $stock;
public function __construct($name, $price, $stock){
$this->name = $name;
$this->price = $price;
$this->stock = $stock;
}
public function sold($num){
if($this->stock > $num){
$this->stock -= $num;
}else{
$this->stock = 0;
}
}
public function arrival($num){
$this->stock += $num;
}
public function showData(){
echo "名前:" . $this->name . "<br>";
echo "値段:" . $this->price . "円<br>";
echo "在庫:" . $this->stock . "<br>";
}
}
?>
これで、商品の枠が完成した。
オブジェクトの使用方法
枠を作っただけでは使えない。
ここからは、この枠を使って実際にオブジェクトを扱う方法を解説する。
最初に、オブジェクトを生成しなければいけない。
その書き方は以下の通り。
変数名 = new クラス名(引数);
これで、クラスの枠に実際のデータが入ったオブジェクトが生成される。
このときに呼び出されるのが、クラス定義内に書いたコンストラクタだ。
つまり、ここの引数はコンストラクタの引数と一致させる必要がある。
そして、オブジェクトを定義したら、その中のプロパティやメソッドにアクセスしたい。
それぞれの書き方は以下の通りだ。
変数名->プロパティ名
変数名->メソッド名(引数)
先ほど、クラス内で自身の内容にアクセスするときに$this->○○
という書き方をしていた。
そのthisが、オブジェクトの入った変数名になったイメージだ。
こちらも、変数名の先頭には$が必要だが、プロパティ名の先頭には$は不要だ。
では、上で定義したProductクラスのオブジェクトを実際に作り、色々といじってみよう。
まず、最初に以下の情報を持つオブジェクトを生成する。
- 商品名:缶コーヒー
- 値段:120
- 在庫:20
そして、10個売れた後、20個入荷したというような処理をしてみよう。
また、オブジェクト生成時とそれぞれの処理後に情報の表示もしてみる。
なお、クラスはProduct.phpというファイルに定義されており、同じディレクトリにあるindex.phpでこれらの処理を行うようにしよう。
<?php
require_once("./Product.php");
$prd = new Product("缶コーヒー", 120, 20);
$prd->showData();
$prd->sold(10);
$prd->showData();
$prd->arrival(20);
$prd->showData();
?>
2行目のrequire_once関数は前回解説した通り、ファイルを読み込む関数だ。
これで、クラスが定義されたファイルを読み込んでいる。
その後、4行目が新しいオブジェクトの生成部分。
このように書くことで、変数$prd
に缶コーヒーの情報が代入されたオブジェクトが入るというわけだ。
その後、各メソッドを呼び出している。
これにアクセスすると、以下のように表示される。
名前:缶コーヒー
値段:120円
在庫:20
名前:缶コーヒー
値段:120円
在庫:10
名前:缶コーヒー
値段:120円
在庫:30
以上が、クラスとオブジェクトの基本的な使い方だ。
なお、今回のサンプルでindex.phpから直接$prd
内のプロパティにアクセスしようとすると、エラーが発生する。
プロパティの定義部分で、アクセス修飾子をprivateにしているからだ。
もしアクセスしてしまうと、Cannot access private property
といった文言が入ったエラーメッセージが表示されてしまう。
例えば、index.phpの最後に$prd->name="";
という行を追加すると、以下のように表示される。
Fatal error: Uncaught Error: Cannot access private property Product::$name in C:\xampp\htdocs\php\sample24\index.php:13 Stack trace: #0 {main} thrown in C:\xampp\htdocs\php\sample24\index.php on line 13
そのアクセスをしているファイルと行番号、アクセスしている対象のクラス名とプロパティ名も表示されているので、それを頼りに修正していこう。
おわりに
今回は、変数や関数を一つのまとまりとして定義するクラスと、それに実際のデータを入れて扱うオブジェクトを解説した。
考え方が複雑になってきたが、クラスの解説はまだまだ残っている。
次回は、基になるクラスの構造に手を加えて別のクラスを作る継承という考え方を解説しよう。
これが分かれば、アクセス修飾子のprotectedの意味も分かるだろう。
分からなくても焦らず、一個一個落ち着いて理解していこう。
コメント