PHP入門 第15回 クラスとオブジェクト
クラスとオブジェクトについて学んでいきます。
クラス
PHP5のクラスの定義は次のような書式を持っています。
1 2 3 4 5 6 7 8 9 |
[abstract|final] class クラス名 [extends クラス名] { クラス定義の本体 } [abstract|final] class クラス名 [inplements インターフェース名] { クラス定義の本体 } |
書式からも抽象クラス、継承、インターフェースをサポートすることが、わかります。
クラス定義の中身にはオブジェクトがもつ変数であるプロパティ、関数であるメソッドを定義します。
キーワード | 説明 |
abstract | 抽象クラスの指定 |
final | 継承不可であることの指定 |
class | クラス定義の開始 |
extends | 継承元のクラス指定 |
implements | 実装するインターフェース名の指定 |
クラスとオブジェクトの利用方法の例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php // クラス定義の開始 class SimpleObject { private $var; // このオブジェクト専用のプロパティ public function __construct($var) { // コンストラクタ $this->var = $var; //オブジェクトのプロパティを初期化 } public function getVar() { //メソッド return $this->var; } } // クラスからインスタンス(オブジェクト)の生成 $obj = new SimpleObject('ABC'); // クラスプロパティを取得して出力 echo $obj->getVar(); // 'ABC’を出力 ?> |
オブジェクトを利用するには、classでクラス定義を行い、new 演算子でオブジェクトを生成します。
生成したオブジェクトのプロパティやメソッドにアクセスするには、
- $this->var
- $obj->getVar()
のように「->」を利用します。
$thisという変数はオブジェクト自身を表す特別な変数です。
プロパティ
オブジェクトは、プロパティと呼ばれるオブジェクト内に保持する変数を定義できます。
プロパティには、public、protected、private キーワードを使用して可視性を指定できるようになっています。
PHP4との互換性のためにvarも使用できますが、PHP5のオブジェクトではvarを使用するべきではありません。
varをPHP5で使用した場合、publicを指定したのと同じ扱いになります。
PHPのクラスのプロパティはデフォルト値を設定できます。
ただし、デフォルト値は定数である必要があります。(PHPのコンパイル時に評価できる値でないといけないからです)
なので、関数からの戻り値などは、プロパティのデフォルト値として利用できません。
(クラスが生成される時に呼び出されるメソッド、コンストラクタにて初期値を設定することができます)
1 2 3 4 5 6 7 |
<?php class SimpleObject { public $a; protected $b; private $c; } ?> |
staticキーワードを使用するとオブジェクトを生成しなくてもプロパティ/メソッドを参照できるようになります。
クラスやオブジェクトのプロパティ/メソッドの参照を指定するためには、”::”スコープ解決演算子を使用します。
1 |
クラス名::$プロパティ名 |
1 2 3 4 5 6 7 |
<?php class SimpleObject { public static $a = "static property"; } echo SimpleObject::$a; ?> |
クラス定義内では、クラス名にself、parentという特別なクラス名が利用できます。
self、parentは小文字でないといけません。
(PHP5から大文字、小文字を区別するようになりました)
名前 | 説明 |
self | オブジェクト自身を意味するクラス名 |
parent | 親オブジェクト(継承元)をいっみするクラス名 |
self、parentを使用してクラス内のプロパティ/メソッドにアクセスした場合、static宣言していない場合、エラーとなってアクセスできません。
self::文を使用してオブジェクト内のプロパティやメソッドにアクセスすることもできますが、普通オブジェクト自身のプロパティにアクセスするには、オブジェクト自身をさす特別な変数"$this”を使用します。
$thisを使用するには、オブジェクトはインスタンス(newを使って生成されたオブジェクト)でないといけません。
オブジェクト定数
値が変更できない定数をクラス内に定義することができます。
クラス内で参照する定数については、クラス外部で定義するよりもクラス内定数として定義することで、定数の意味合いが視覚的にもわかりやすくなります。
定数は、通常の変数とは異なり、定義または使用する際に $ 記号を付けません。
定義する値は定数表現である必要があり、変数・クラスのメンバー・ 演算結果あるいは関数のコールなどであってはいけません。
インターフェイスに 定数 を持たせることもできます。
1 |
const 定数名 = 値; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php class MyClass { const constant = 'constant value'; function showConstant() { echo self::constant . "\n"; } } echo MyClass::constant . "\n"; $classname = "MyClass"; echo $classname::constant . "\n"; // PHP 5.3.0 以降で対応 $class = new MyClass(); $class->showConstant(); echo $class::constant."\n"; // PHP 5.3.0 以降で対応 ?> |
メソッド
メソッドとは、オブジェクトがデータ操作などに必要とする手続きを定義した関数です。
メソッドは通常の関数と同じように定義できます。
プロパティと同じようにメソッドにも可視性を指定できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php class SimpleObject { public $a; protected $b; private $c; function __construct($a, $b, $c = null) { $this->a = $a; $this->b = $b; $this->c = $c; } public function getA() { return $this->a; } public function getB() { return $this->b; } public function getC() { return $this->c; } } $obj = new SimpleObject(1, 2); echo $obj->getA(); //「1」を出力 echo $obj->getB(); //「2」を出力 echo $obj->getC(); //出力結果なし ?> |
$thisは、オブジェクト自身を参照する特別な変数です。
オブジェクト自身のプロパティやメソッドにアクセスする場合に$this変数を利用します。
$thisは特別な変数の為、上書きするとエラーが発生します。
(PHP4まではエラーは発生しません)
特別な意味をもつメソッドが定められています。
それは、オブジェクト生成時に自動的に呼び出される関数や、オブジェクト消滅時に自動的に呼び出される関数などです。
以下に特別なメソッドの一覧になります。
メソッド名 | 説明 |
__constructor | オブジェクト生成時に呼び出される関数 |
__destructor | オブジェクト破棄時に呼び出される関数 |
__get | 存在しないプロパティを参照しようとしたときに呼び出される関数 |
__set | 存在しないプロパティを設定しようとしたときに呼び出される関数 |
__call | 存在しないメソッドを呼び出した時に呼び出される関数 |
__wakeup | unserialize関数でオブジェクトを再生成する場合に呼び出される関数 |
__sleep | serialize関数でオブジェクトを永続化する場合にに呼び出される関数 |
__toString | オブジェクトをprint/echoで出力する時に呼び出される関数 (文字列型にオブジェクトを変換しようとした時) |
__clone | cloneステートメントが呼び出された時に呼び出される関数 |
コンストラクタ
オブジェクトを生成する際に、オブジェクトを初期化するコードを記述するメソッドのことをコンストラクタといいます。
コンストラクタは、定義されていなくてもかまいません。
1 2 3 4 5 |
class クラス名 { void function __construct([mixed 変数 [,・・・]]) { 文 } } |
コンストラクタの使用例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php class SimpleObject { public $var; // コンストラクタを定義 function __construct($var) { $this->var = $var; } } // コンストラクタに引数を渡してオブジェクトを生成 $obj = new SimpleObject('TEST'); echo $obj->var; // 「TEST」を出力 ?> |
PHP5では、___construct()をコンストラクタとして使用します。
継承を利用している場合、親クラスのコンストラクタは自動的には呼び出されません。
親クラスのコンストラクタを呼び出す為には、明示的に呼び出す必要があります。
PHP4ではクラス名と同じ名前を持つメソッドがコンストラクタとして扱われます。
PHP5でも互換性を持たせる為に、クラス名と同じメソッド名をコンストラクタとして利用できます。
ですが、__construct()をコンストラクタとして使用するほうがいいでしょう。
デストラクタ
オブジェクトが消滅する際に、自動的に呼び出されるメソッドのことをデストラクタといいます。
デストラクタは、定義されていなくてもかまいません。
1 2 3 4 5 |
class クラス名 { void function __destruct(void) { 文 } } |
デストラクタの使用例)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php class SimpleObject { // デストラクタを定義 function __destruct() { echo __METHOD__.' is called'; } } // オブジェクトを生成 $obj = new SimpleObject(); //「SimpleObject::__destruct is called」と出力されます。 ?> |
PHP5では、___destruct()をデストラクタとして使用します。
継承を利用している場合、親クラスのデストラクタは自動的には呼び出されません。
親クラスのデストラクタを呼び出す為には、明示的に呼び出す必要があります。
デストラクタは、PHP5からサポートされました、ですのでPHP4では使用することはできません。
継承
継承とは、あるクラスの機能を引き継ぎながら、既存のプロパティ/メソッドを上書きしたり、あらたなメソッドを追加することを言います。
extendsキーワードを使用することで、指定されたクラスを継承するこtが可能になります。
継承してできたクラスをサブクラス(子クラス、派生クラス)と言い、継承元のクラスのことをスーパークラス(親クラス、基底クラス)と言います。
継承の世代数に制限はありませんが、複数の親クラスからの継承(多重継承)はサポートされていません。
継承を利用することで、コードの再利用性を高めることができます。
1 2 3 |
class クラス名 extends 親クラス { 文 } |
継承の使用例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php class Graphics { public $x, $y; function test() { $x = 1; $y = 1; } function triangle($num1, $num2) { $this->x = $num1; $this->y = $num2; return $this->x * $this->y /2; } } // Graphicsクラスを継承したGraphicsUpクラスを定義 class GraphicsUp extends Graphics { function square($num1, $num2) { $this->x = $num1; $this->y = $num2; return $this->x * $this->y; } } $obj = new GraphicsUp(); echo $obj->triangle(10,2); // 親クラスのtriangleメソッドを実行した結果が得られます。出力結果:「10」 echo $obj->square(10,2); // 子クラスのsquareメソッドを実行した結果が得られます。出力結果:「20」 ?> |
オーバーライド
オーバーライドとは、親クラスに存在するプロパティ/メソッドと同じ名前のプロパティ/メソッドを子クラスで再定義することをいいます。
オーバーライドされたプロパティ/メソッドは明示的に親クラスのものを参照する意味をもつ「parent」を使用して参照することができます。
オーバーライドしたプロパティ/メソッドの使用例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<pre> <?php //親クラスの定義 class ParentObject { private $property = __CLASS__; public function Method() { echo __METHOD__."\r\n"; // 「ParentObject::Method」を出力 } public function OtherMethod() { echo __METHOD__."\r\n"; // 「ParentObject::OtherMethod」を出力 } public function GetProperty() { echo $this->property."\r\n"; } } //子クラスの定義 class ChildObject extends ParentObject { public $property = __CLASS__; //ParentObject::Method()をオーバーライド public function Method() { echo __METHOD__."\r\n"; // 「ChildObject::Method」を出力 } } $p = new ParentObject(); var_dump($p); //子クラスのインスタンスを生成 $c = new ChildObject(); $c->Method(); // 子クラスがオーバーライドしたメソッド $c->OtherMethod(); // オーバーライドされていない親クラスのメソッド $c->GetProperty(); // オーバーライドされた親クラスのプロパティ echo $c->property; // オーバーライドしたプロパティ ?> </pre> |
カプセル化
オブジェクト内部のプロパティを隠し、公開されたメソッドのみを利用してアクセスできるようにすることです。
Java、C++などの多くのオブジェクト指向型のプログラミング言語がもっている考え方と同様です。
キーワード | 説明 |
public | 公開されている |
protected | 継承したクラスのみに公開 |
private | 非公開:同じクラス内からのみ参照可能 |
これらのキーワードは、クラス内のプロパティ/メソッド共に利用可能です。
メソッド宣言の可視性キーワードは省略できます。
省略した場合は、public static 宣言されたことと同等になります。
静的なプロパティとメソッド
関数に性的な変数を定義するstaticキーワードはプロパティとメソッドにも使用できます。
静的なプロパティ/メソッドとは、インスタンス(newを使用してオブジェクト生成すること)を生成しなくてもプロパティやメソッドが初期化/使用できるものの事を言います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<pre> <?php class SimpleObject { public static $cnt = 0; public static function increment() { self::$cnt++; // $this ではなくselfを使用しないとエラーとなる } } // 静的なプロパティとメソッドはインスタンスなしに利用できます。 echo SimpleObject::$cnt."\r\n"; // 0を出力 SimpleObject::increment(); // インクリメント echo SimpleObject::$cnt."\r\n"; // 1を出力 ?> </pre> |
抽象クラス(abstract class)と抽象メソッド(abstract method)
抽象クラスとは、インスタンスを作れないクラスです。
抽象メソッドとは中身の定義がなく、子クラスが必ず中身を定義しなければならないメソッドのことです。
abstractキーワードを利用して抽象クラス、抽象メソッドを作成できます。
抽象メソッドを持つクラスは、必ず抽象クラスとして定義されなければなりません。
抽象メソッドを持つクラスを継承したクラスは、必ず全ての抽象メソッドを実装しなければなりません。
抽象メソッドを実装するメソッドは引数の数も一致していなければなりません。
インターフェース
インターフェースとはクラスが定義すべきメソッドを指定する仕組みです。
インターフェース定義自体はメソッドが何をするのか定義する必要はありません。
クラス定義にメソッドの実装を強制する抽象クラスとにています。
抽象メソッドと同じでインターフェースで定義されているメソッドは全て実装しなければなりません。
引数の数も抽象メソッドと同じく一致している必要があります。
final宣言
通常のクラスやメソッドは、自由に拡張できますが、クラスライブラリを作成する場合、拡張を制限したい場合もあります。
クラスの継承を制限したり、メソッドのオーバーライドを制限するためにfinalキーワードが用意されています。
1 2 3 4 5 |
final class クラス名 { クラス定義の本体 } final class クラス名 { final [public|protected|private] function 関数名 { 関数定義の本体 } } |
final宣言されたクラスはどのような場合でも継承元になることはできません。
final宣言されたメソッドを持つクラスは、クラス自体がfinal宣言されていなければ継承元の親クラスとなれますが、finalメソッドはオーバーライドできません。
オブジェクトの比較
オブジェクトの比較を行った場合、”==”はオブジェクト名/プロパティの値が同じか比較しTRUE/FALSEを返します。
”===”は、オブジェクトハンドルが同じ場合にのみ一致したと判断されます。
(PHP4では、”==”も”===”も判断は、オブジェクト名/プロパティの値が同じかどうかで判断されます)
オブジェクトのクローン
オブジェクトは、代入演算子"="では、コピーできません。
(オブジェクトハンドルの代入になります)
オブジェクト型のコピーを作成したい場合は、clone文を使用します。
1 2 |
$コピー先オブジェクト名 = clone $コピー元オブジェクト名; $コピー先オブジェクト名 = clone($コピー元オブジェクト名); |
クローンと代入演算子を使用した比較例)
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php class Object {} $obj = new Object(); $o1 = $obj; $o2 = clone $obj; var_dump($o1 === $obj); // true var_dump($o2 === $obj); // false ?> |
オブジェクトのクローンを作成する際は、PHPはプロパティをありのままこぴーします。
例えば、オブジェクトハンドルはハンドルとしてコピーされます。
他の変数への参照も、参照のままコピーされます。
このようなコピーでは困る場合は、明示的にコピー方法を指定できます。
オブジェクトにclone文が使用された場合、__cloneメソッドが定義されていると__cloneメソッドで定義された手順でオブジェクトがコピーされます。
1 |
void __clone(void) { メソッド本体の定義 } |
オートロード
クラス定義が行われていないクラスをインスタンス化しようとした場合、自動的にファイルを呼び込む機能
PHP5でプログラム中に未定義のクラス名があると、クラス名を引数として自動的に__autoload関数を呼び出します。
1 |
void function __autoload($クラス名); |
__autoload関数が定義されていない場合や、__autoload関数を使用してもクラス定義が見つからない場合は、未定義のクラス名を使用されたことになり、エラーとなります。
__autoloadのエラーはcatch文でキャッチできないので、注意が必要です。
コメント:1件
トラックバック:1件
-
[...] 第15回 クラスとオブジェクト [...]
クラスとオブジェクト 解りやすく1頁にまとめていただきありがとうございます。
PHP5の勉強をさぼっていたので、とても勉強になりました。
どのページも読んでいて楽しくためになります。
ありがとうございました。