class はクラスを定義します。PHPも他のオブジェクト指向言語と同様、クラスやクラスの継承をサポートします。下記の例は MyMember クラスを定義しています。MyMember クラスはプロパティとして $name を持ちます。また、メソッドとして $name に値を設定する setName() と、$name の値を参照する getName() を持ちます。$this は特別な値で、自分自身のオブジェクトを指します。
<?php class MyMember { private $name; function setName($name) { $this->name = $name; } function getName() { return $this->name; } }
new 演算子でオブジェクトを生成し、setName() メソッドを呼び出して名前を設定し、getName() メソッドでその値を参照しています。オブジェクトのプロパティやメソッドを参照するには、-> を用います。
$foo = new MyMember(); $foo->setName("Tanaka"); echo $foo->getName() . "\n";
extends はクラスを継承する際の親クラスを指定します。下記の例で、 MyMember2クラスは、MyMemberクラスを継承するサブクラスとして定義されています。MyMember2クラスは、MyMemberクラスが持つ $nameプロパティ、setName()メソッド、getName()メソッドを引き継ぎ、加えて、$addrプロパティ、setAddr()メソッド、getAddr()メソッドを持ちます。
<?php class MyMember { private $name; function setName($name) { $this->name = $name; } function getName() { return $this->name; } } class MyMember2 extends MyMember { private $addr; function setAddr($addr) { $this->addr = $addr; } function getAddr() { return $this->addr; } } $foo = new MyMember2(); $foo->setName("Tanaka"); $foo->setAddr("Tokyo"); echo "name = {$foo->getName()}\n"; echo "addr = {$foo->getAddr()}\n";
const はクラス定数を定義します。クラス定数はインスタンス化しなくても参照可能です。クラス名::定数名 で参照します。
<?php class MyMath { const PI = 3.14; } echo MyMath::PI;
static はスタティック変数を定義します。スタティック変数はインスタンス化しなくても参照可能です。クラス名::$変数名 で参照します。定義後でも変更可能である点がクラス定数と異なります。
<?php class MyMath { public static $debug_level = 0; } MyMath::$debug_level = 9; echo MyMath::$debug_level . "\n";
static はまた、スタティックメソッドを定義します。スタティックメソッドもインスタンス化しなくても利用可能です。クラス名::メソッド名() で参照します。
<?php class MyMath { public static function add($x, $y) { return $x + $y; } } echo MyMath::add(3, 5);
スコープ演算子(::)は、クラス定数、スタティック変数、スタティックメソッドにアクセスする際に用いられます。
<?php class MyMath { const PI = 3.14; public static $debug_level = 0; public static function add($x, $y) { return $x + $y; } } echo MyMath::PI . "\n"; echo MyMath::$debug_level . "\n"; echo MyMath::add(3, 5) . "\n";
self:: は、自クラスを示します。クラス定数、スタティック変数、スタティックメソッドについては、インスタンス化せずに使用するため、$this は使用できず、代わりに self を使用します。
<?php class MyMath { const PI = 3.14; public static $debug_level = 0; public static function add($x, $y) { return $x + $y; } function test() { echo self::PI . "\n"; echo self::$debug_level . "\n"; echo self::add(3, 5) . "\n"; } }
parent:: は、親クラスを示します。
<?php class MyClass1 { function func1() { echo "func1()\n"; } } class MyClass2 extends MyClass1 { function func2() { parent::func1(); } }
クラスが持つプロパティの宣言は、PHP 4 までは var を用いていましたが、PHP 5 からは、public、protected、private のいずれかを使用することが推奨されています。public はどこからでもアクセスできます。protected は、そのクラス自身、継承したクラス、親クラスからアクセスできます。private はそのクラス自身からのみアクセスできます。
<?php class MyClass1 { // 親クラス function func1() { echo $this->var; echo $this->pub; echo $this->pro; # echo $this->pri; // アクセスできない } } class MyClass2 extends MyClass1 { // 自クラス var $var = "var\n"; public $pub = "public\n"; protected $pro = "protected\n"; private $pri = "private\n"; function func2() { echo $this->var; echo $this->pub; echo $this->pro; echo $this->pri; } } class MyClass3 extends MyClass2 { // 子孫クラス function func3() { echo $this->var; echo $this->pub; echo $this->pro; # echo $this->pri; // アクセスできない } } $obj = new MyClass3(); $obj->func1(); $obj->func2(); $obj->func3(); echo $obj->var; echo $obj->pub; # echo $obj->pro; // アクセスできない # echo $obj->pri; // アクセスできない
var | public | protected | private | |
---|---|---|---|---|
親クラス | ○ | ○ | ○ | × |
自クラス | ○ | ○ | ○ | ○ |
子孫クラス | ○ | ○ | ○ | × |
その他 | ○ | ○ | × | × |
__construct() はコンストラクタと呼ばれ、オブジェクト生成時に暗黙的に呼び出されます。
<?php class MyClass { function __construct() { echo "Constructer of MyClass\n"; } } $obj = new MyClass(); // オブジェクト生成時に自動的に __construct() メソッドが呼ばれます
祖先となるクラスがコンストラクタを持っている場合は、子孫クラスは parent::__construct() を明示的に呼び出す必要があります。
<?php class MyClass1 { function __construct() { echo "MyClass1\n"; } } class MyClass2 extends MyClass1 { function __construct() { parent::__construct(); echo "MyClass2\n"; } } $obj = new MyClass2();
__destuct() はデストラクタと呼ばれ、オブジェクト消滅時に暗黙的に呼び出されます。
<?php class MyClass1 { function __destruct() { echo "MyClass1\n"; } } class MyClass2 extends MyClass1 { function __destruct() { parent::__destruct(); echo "MyClass2\n"; } } $obj = new MyClass2(); unset($obj); // オブジェクト消滅時にデストラクタが呼ばれる
クラスのプロパティやメソッドは、サブクラスでオーバーライド(上書き)することができます。下記の例では、親クラスが持つ func() というメソッドを、サブクラスがオーバーライドしています。
<?php class MyClass1 { public function func() { echo "AAA\n"; } } class MyClass2 extends MyClass1 { public function func() { echo "BBB\n"; } } $obj = new MyClass2(); $obj->func(); // BBB と表示される
final をつけたメソッドは、サブクラスでオーバーライドすることができません。
<?php class MyClass1 { final public function func() { echo "AAA\n"; } } class MyClass2 extends MyClass1 { # public function func() { echo "BBB\n"; } // オーバーライドが禁止される } $obj = new MyClass2(); $obj->func(); // BBB と表示される
abstract は、抽象クラスを定義します。抽象クラスはそのままではオブジェクト化することができず、必ずそのサブクラスを定義してオブジェクト化します。抽象クラスは、サブクラスが必ず定義しなくてはならない抽象メソッドを定義します。サブクラスで定義を怠ると、PHP文法エラーとなります。これにより、抽象クラスを継承するすべてのサブクラスが、必要なメソッドを持っていることが保障されます。
<?php abstract class MyFileReader { // 抽象クラスとして定義 protected $file_name; protected $fp; function __construct($file) { // 初期化処理(ファイルのオープンなど) } abstract public function read(); // ひとつ以上の抽象メソッドを定義 function close() { // ファイルのクローズ処理 } } class MyCsvFileReader extends MyFileReader { public function read() { // 抽象メソッドを具現化 // CSVファイル読み込み処理 } } class MyXmlFileReader extends MyFileReader { public function read() { // 抽象メソッドを具現化 // XMLファイル読み込み処理 } } $fr = new MyCsvFileReader("sample.csv"); $csv = $fr->read(); $fr->close();
interface は、インタフェースを定義します。インタフェースはそのままではオブジェクト化することができず、必ずそのインタフェースを実装するクラスを定義してオブジェクト化します。インタフェースは、実装クラスが必ず定義しなくてはならないメソッドを定義します。
<?php interface MyFileReader { // インタフェースとして定義 public function read(); // クラスが実装すべきメソッドを定義 } class MyCsvFileReader implements MyFileReader { public function read() { // メソッドを具現化 // CSVファイル読み込み処理 } } class MyXmlFileReader implements MyFileReader { public function read() { // メソッドを具現化 // XMLファイル読み込み処理 } } $fr = new MyCsvFileReader("sample.csv"); $csv = $fr->read(); $fr->close();
抽象クラスとインタフェースは似ていますが、抽象クラスがメソッドの実態を定義できるのに対し、インタフェースは実態を定義することはできません。その代わりに、抽象クラスはひとつしか継承できないのに対し、インタフェースは複数実装することが可能です。
class MyClass implements MyInterface1, MyInterface2 { public function func1() { /* func1()の実装 */ } public function func2() { /* func2()の実装 */ } }
PHP5 では、メソッドに引数の型を指定することが可能となりました。異なる型の引数を指定するとPHPエラーが発生します。これにより、プログラム引数のミスを抑制することができます。ただし、型として指定できるのは、クラス名(PHP5~)、インタフェース名(PHP5~)、配列(array)(PHP 5.1~)、コールバック関数(callable)(PHP5.4~)のみで、int, integer, string などのスカラー型を指定することはできません。
<?php class MyClass1 { public function greet() { echo "Hello\n"; } } class MyClass2 { public function greet() { echo "Guten Tag\n"; } } class MyClass3 { public function test(MyClass1 $obj) { $obj->greet(); } } $obj1 = new MyClass1(); $obj2 = new MyClass2(); $obj3 = new MyClass3(); $obj3->test($obj1); // 型が合っているので呼び出せる # $obj3->test($obj2); // 型が合っていないのでエラーとなる
オートローディング機能を用いることで、クラスが定義されたファイルを自動的に読み込むことが可能です。new でクラスが生成される際、該当するクラスが定義されてなければ、__autoload() 関数が呼ばれます。下記の例では、MyClass1 を new する際に、MyClass1.php ファイルが自動的にインクルードされます。
<?php function __autoload($class_name) { include("{$class_name}.php"); } $obj = new MyClass1();
PHP 5.1.2 以降では、__autoload() の代わりに spl_autoload_register() を使用するようになりました。__autoload() は一度しか定義できませんが、spl_autoload_register() は状況に応じて読み込み方法を変更することが可能です。
<?php spl_autoload_register(function($class_name) { include("{$class_name}.php"); }); $obj1 = new MyClass1();
下記の例では、Model_MyClass1.php を new すると、Model/MyClass1.php が読み込まれます。
<?php spl_autoload_register(function($class_name) { include(str_replace("_", "/", $class_name) . ".php"); }); $obj1 = new Model_MyClass1();
= 演算子でオブジェクトを代入すると、オブジェクトへの参照が代入されます。
<?php class MyClass { public $name; } $obj1 = new MyClass(); $obj1->name = "AAA"; $obj2 = $obj1; // $obj2 は $obj1 と同じオブジェクトを示す $obj2->name = "BBB"; echo $obj1->name . "\n"; // BBB と表示される echo $obj2->name . "\n"; // BBB と表示される
clone を用いることで、オブジェクトの複製(クローン)を作成することができます。
<?php class MyClass { public $name; } $obj1 = new MyClass(); $obj1->name = "AAA"; $obj2 = clone $obj1; // $obj1 とは別のオブジェクトが生成される $obj2->name = "BBB"; echo $obj1->name . "\n"; // AAA と表示される echo $obj2->name . "\n"; // BBB と表示される