オブジェクト指向言語に生まれ変わるPHP5[前編]

ベータリリース目前!? PHP5の新機能

小山 哲志

2003/4/25

 PHP5の新機能

 それではPHP5(ZE2)で強化された機能を順に見ていこう。まずは目玉であるオブジェクト指向機能だが、クラス周りの実装が大きく修正された。クラスに関する新機能だけでもこれだけある。

  • オブジェクトは参照渡しがデフォルト
  • プロパティにアクセス制限を導入
  • メソッドにアクセス制限を導入
  • abstractクラスとabstractメソッド
  • インターフェイス
  • final宣言
  • 名前空間
  • クラス内定数
  • クラス変数
  • 統一コンストラクタ
  • デストラクタ
  • アクセサ

 なお今回紹介する内容は、2003年4月22日時点でCVSに登録されているバージョンに基づいていることをお断りしておく。正式リリースまでの間に、言語仕様が若干変更される可能性もないわけではない。

オブジェクトは参照渡しがデフォルト

 PHP4では、変数$var1オブジェクトの場合、

$var2 = $var1;

と記述すると、$var2には$var1のコピーが代入された。明示的に$var2が$var1と同じオブジェクトを指すようにするには、

$var2 =& $var1;

と、「&」を追加して参照として代入する必要があった。

 PHP5では、オブジェクト変数の代入は自動的に参照渡しになる。つまり、

$var2 = $var1;

で、$var2と$var1は同じオブジェクトを指すようになる。PHP4と同様にコピーを代入したい場合は、新たに導入された__clone()()というメソッドを用いる。

$var2 = $var1->__clone();

【注】
__clone()の「__」は、「_」が2つ連続している。

プロパティにアクセス制限を導入

 PHP4のクラスは、プロパティ(C++でいうところのメンバ変数)、メソッド(同じくメンバ関数)ともに、クラスの内外どこからでもアクセスでき、アクセス制限を掛けることはできなかった。このため、ユーザーがクラスのプロパティを不用意に変更することを防ぐことはできない。

 PHP5では、C++やJavaと同様にprivate、protected、publicの3レベルのアクセス制限を導入し、クラス設計者がプロパティとメソッドに対して使用方法を限定できるようになっている。プロパティに対するそれぞれのアクセス制限の意味は以下のとおり。

public クラスの内外に限らず、どこからでも参照/変更が可能
private そのクラスのメソッドの中からのみ参照/変更が可能
protected そのクラスとそのクラスを継承したクラスのメソッドの中で参照/変更が可能。また継承したクラスの中ではアクセス指定を上書きすることができる

 PHP4での書式だった「var」は、従来と同様にpublicと同じ意味に扱われる。それでは実例を挙げて、アクセス制限がどのように作用するか見ていこう。

class Hoge1 {
  private $var1 = 'A';
  protected $var2 = 'B';
  protected $var3 = 'C';

  function setLower() {
    $this->var1 = 'a';
    $this->var2 = 'b';
    $this->var3 = 'c';
  }
  function var1() {
    return $this->var1;
  }
  function var2() {
    return $this->var2;
  }
  function var3() {
    return $this->var3;
  }
}

 このクラスは、$var1、$var2、$var3の3つのプロパティを持っている。$var1はprivateで宣言されており、$var2と$var3はprotectedだ。ここで、

$hoge = new Hoge1;
echo 'var1: ' . $hoge->var1 . "<br>\n";

として外部からのアクセスが許されないprivateなプロパティを参照してみると、

Fatal error: Cannot access private property hoge1::$var1 in /path/to/script.php on line XX

のようにエラーが発生する。protectedな$var2に対しても同様だ。

 private、protectedともに、Hoge1のメソッドからアクセスする分には問題ないので、以下のコードはどれも正常に動作する。

echo 'var1: ' . $hoge->var1() . "<br>\n";  // var1: A
echo 'var2: ' . $hoge->var2() . "<br>\n";  // var2: B
echo 'var3: ' . $hoge->var3() . "<br>\n";  // var3: C

$hoge->setLower();

echo 'var1: ' . $hoge->var1() . "<br>\n";  // var1: a
echo 'var2: ' . $hoge->var2() . "<br>\n";  // var2: b
echo 'var3: ' . $hoge->var3() . "<br>\n";  // var3: c

 次に、protectedなプロパティの挙動を見るために、Hoge1を継承したクラスHoge2を作ってみよう。

class Hoge2 extends Hoge1 {
  public $var3 = '3';

  function d_var1() {
    return $this->var1;
  }
  function d_var2() {
    return $this->var2;
  }
  function d_var3() {
    return $this->var3;
  }
}

 クラスHoge2では、$var3のみpublicプロパティとして宣言している。プロパティがprotectedの場合、そのサブクラスからアクセスがどの制限になるかは、サブクラスのプロパティ宣言のみによって決まる。Hoge2の場合は、$var3がpublicとして宣言されているので、どこからでもHoge2の$var3(実体はHoge1の$var3)にアクセスできることになる。$var1の場合は、Hoge1でprivate宣言されているので、サブクラスであるHoge2には何の影響も及ぼさない。

 Hoge2で新たに$var1というプロパティを作成することさえ可能で、その場合はHoge1::$var1とHoge2::$var1は明確に区別される。

$hoge = new Hoge2;

echo 'var1: ' . $hoge->var1 . "<br>\n";      // var1:
// echo 'var2: ' . $hoge->var2 . "<br>\n";   // Error
echo 'var3: ' . $hoge->var3 . "<br>\n";      // var3: 3

echo 'var1: ' . $hoge->d_var1() . "<br>\n";  // var1:
echo 'var2: ' . $hoge->d_var2() . "<br>\n";  // var2: B
echo 'var3: ' . $hoge->d_var3() . "<br>\n";  // var3: 3

 実際にHoge2のオブジェクトを作成して、いろいろアクセスしてみると上記の結果になる。$hoge->var1はHoge1::$var1と無関係な変数になるので、何も表示されない。$var2をメソッドを通さずに直接参照すると、protectedのアクセス制限に引っ掛かり、Fatal Errorになる。

メソッドにアクセス制限を導入

 プロパティと同様に、メソッドにもアクセス制限を追加できるようになった。こちらもprivate、protected、publicの3種類で、それぞれ、

public どこからでも呼び出し可能
private そのクラスのメソッド内からのみ呼び出し可能
protected そのクラスとサブクラスのメソッド内からのみ呼び出し可能

となる。こちらはJavaやC++の意味合いと同じなので混乱することはないだろう。

abstractクラスとabstractメソッド

 Javaと同様のabstractクラスとabstractメソッドがサポートされた。abstractメソッドはメソッド名の呼び出し方法だけを提供し、実装は提供しない。またabstractメソッドを持つクラスは、クラス自体もabstract宣言しなければならない。もしabstractクラスのオブジェクトを直接作成しようとすると、

Fatal error: Cannot instantiate abstract class ClassName

というエラーが発生する。実際の使用例は以下のとおり。

<?php

abstract class MyAbstract {
  abstract public function test();
  public function test2() {
    echo "MyAbstract::test2() called.<br>\n";
  }
}

class MyImplement extends MyAbstract {
  public function test() {
    echo "MyImplement::test() called.<br>\n";
  }
}

$obj = new MyImplement;
$obj->test();

?>

インターフェイス

 Javaと同様のinterfaceがサポートされた。interfaceは、機能の外部仕様を記述するのに適した仕組みである。

 interfaceそのものに実装を記述することはできない。逆にinterfaceを実装(implements)するクラスは、そのinterfaceのメソッドに対する実装を必ず持っていなければならない。また、クラスは複数のinterfaceを実装することができ、これにより多重継承とほぼ同じことを実現可能だ。

<?php
interface Throwable {
  public function getMessage();
}

interface Serializable {
  public function toString();
}

class MyException implements Throwable, Serializable {
  public function getMessage() {
    return 'this is MyException message';
  }

  public function toString() {
    return 'MyException: this is MyException message';
  }
}

$e = new MyException;
echo $e->getMessage();
echo $e->toString();
?>

final宣言

 これもJava同様、final宣言がサポートされた。メソッドに対してfinal宣言を追加しておくと、そのメソッドはサブクラスでオーバーライドされないことが保証される。finalで宣言されているにもかかわらず、サブクラスでオーバーライドしようとすると、

Fatal error: Cannot override final method fuga::foo()

というエラーになる。

<?php
class Fuga {
  final function foo() {
    echo "this is final function\n";
  }
}

class Hoge extends Fuga {
  function foo() {
    echo "this is not final function\n";
  }
}
?>

 前編はここまでである。後編「PHP5の新機能とPHP4との互換性」ではクラス機能の残りと、そのほかに拡張される機能について解説する。お楽しみに。

2/2
 

Index
ベータリリース目前!? PHP5の新機能
  Page1
Zend Engine 2.0の誕生
 PHP4の限界
 Zend Engine 2.0の開発開始
Page2
PHP5の新機能
 オブジェクトは参照渡しがデフォルト
 プロパティにアクセス制限を導入
 メソッドにアクセス制限を導入
 abstractクラスとabstractメソッド
 インターフェイス
 final宣言

オブジェクト指向言語に生まれ変わるPHP5

 PHP関連記事
例外処理の実装を把握する
PHP5で広がる! 開発環境(1)
 PHP4のサポートが終了し、いよいよPHP5への移行を視野に入れる時期が来た。PHP5の機能を生かした開発のポイントを紹介
クライアントPCに言語環境を入れる理由
Mac OS X+PHPでオールインワン環境(準備編)
 Webアプリ開発者に人気のMac OS X。効率的な開発のために複数バージョンのPHPを実行する環境を構築してみよう
PHPに押し寄せるリスクと国際化の波
PHPカンファレンス2008レポート(前編)
 PHP4のサポートが完全に終了する。多くの新機能が投入されるPHP5.3へ移行か、国際化対応で開発が遅れるPHP6を待つか
PHPによる大規模商用サービスの裏側
PHPカンファレンス2008レポート(中編)
 企業のWebアプリケーション開発現場で利用されるPHP。開発現場の裏側にはさまざまなドラマが隠されている
PHPユーザーは本当にほかの言語を知らないのか?
PHPカンファレンス2008レポート(後編)
 PHPは本当にダメな言語なのだろうか。Perl、Ruby、Python、Java、JavaScriptの使い手が白熱した議論を行った
  Coding Edgeフォーラムフィード  2.01.00.91


Coding Edge フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

>

Coding Edge 記事ランキング

本日 月間