第 18章クラスとオブジェクト (PHP 4)

クラス

クラスは、変数およびこれらの変数で動作する関数の集まりです。 クラスは次のような構文により定義されます。

<?php
class Cart
{
    var
$items ;   // 買い物カゴの中のアイテム

    // $num 個の $artnr を買い物カゴに加えます

    
function add_item ( $artnr , $num )
    {
        
$this -> items [ $artnr ] += $num ;
    }

    
// $num 個の $artnr を買い物カゴから出します

    
function remove_item ( $artnr , $num )
    {
        if (
$this -> items [ $artnr ] > $num ) {
            
$this -> items [ $artnr ] -= $num ;
            return
true ;
        } elseif (
$this -> items [ $artnr ] == $num ) {
            unset(
$this -> items [ $artnr ]);
            return
true ;
        } else {
            return
false ;
        }
    }
}
?>

この例は、買い物カゴの中の物の連想配列と、買い物カゴにアイテムを加えたり 除いたりする二つの関数からなる Cart という名前のクラスを 定義します。

警告

複数のファイルで分割してクラスを定義することは できません 。また、関数定義の内部分割されている 場合を除き、複数の PHP ブロックで分割してクラスを定義することも できません 。次の例は正しく動作しません:

<?php
class test {
?>
<?php
    
function test () {
        print
'OK' ;
    }
}
?>

しかし、次の例は許されます:

<?php
class test {
    function
test () {
        
?>
         <?php
        
print 'OK' ;
    }
}
?>

以下の注意書きはPHP 4に関するものです。

注意

名前 stdClass は、Zendにより内部的に使用され、保 存されています。PHPで stdClass という名前のクラ スを使用することはできません。

注意

関数 __sleep および __wakeup は、 PHPクラス内で使用される特殊な関数です。これらの関数に付随する特殊 な機能を使用する場合以外は、クラス内でこれらの名前を付けた関数を 使用することはできません。詳細な情報については、以下を参照ください。

注意

PHP は、__で始まる全ての関数名を特殊な関数として予約しています。 ドキュメントに記載された特殊関数の機能を使用する場合以外は、__を 有する関数名を使用しないことを推奨します。

PHP 4では、変数 var については定数による初期化の みが可能です。定数以外で初期化を行う場合には初期化関数が必要です。 この初期化関数は、オブジェクトがクラスから構築される際に自動的に コールされます。このような関数はコンストラクタと呼ばれます。(以下 参照)

<?php
class Cart
{
    
/* 以下のコードはPHP 4では動作しません。 */
    
var $todays_date = date ( "Y-m-d" );
    var
$name = $firstname ;
    var
$owner = 'Fred ' . 'Jones' ;
    
/* Arrays containing constant values will, though. */
    
var $items = array( "VCR" , "TV" );
}

/* 以下に正しい方法を示します。 */
class Cart
{
    var
$todays_date ;
    var
$name ;
    var
$owner ;
    var
$items = array( "VCR" , "TV" );

    function
Cart ()
    {
        
$this -> todays_date = date ( "Y-m-d" );
        
$this -> name = $GLOBALS [ 'firstname' ];
        
/* 等など. . . */
    
}
}
?>

クラスは型、つまり、実際の変数の雛型です。 new 演 算子により所望の型の変数を作成する必要があります。

<?php
$cart
= new Cart ;
$cart -> add_item ( "10" , 1 );

$another_cart = new Cart ;
$another_cart -> add_item ( "0815" , 3 );
?>

この例は、クラスCartのオブジェクト $cart および $another_cart を作成します。 $cart オブジェクトの関数 add_item()が商品番号10の商品一つが カートに追加されています。商品番号0815の商品3つが $another_cart に追加されています。

$cart $another_cart は共に関数 add_item()、 remove_item() と変数items を有しています。これらは、異なる関数および変数です。 オブジェクトは、ファイルシステムのディレクトリに似たようなものであると 考えられます。ファイルシステムでは、別のディレクトリに置く限り、 二つの異なる README.TXT を保持することが可能です。 ディレクトリではトップディレクトリから各ファイルにアクセスするには、 フルパス名を入力する必要がありますが、これと全く同様にコールしたい 関数の完全な名前を指定する必要があります。PHPの用語では、最上位の ディレクトリはグローバル名前空間であり、パス名のセパレータは、 -> となります。つまり、 $cart->items $another_cart->items は、二つの異なる変数です。 $cart->items という名前の変数は、 $cart->$items ではない、つまり、PHP の変数名は ドル記号を一つだけ有することに注意してください。

// 正しい、$は一つ
$cart->items  = array("10" => 1);

// $cart->$items は、$cart->"" になるため、正しくない。
$cart->$items = array("10" => 1);

// 正しいが、意図しているかどうかによらず、
// $cart->$myvar は、 $cart->items となる
$myvar = 'items';
$cart->$myvar = array("10" => 1);

クラス定義の内部では、プログラムでアクセス可能なオブジェクト名を知ることはできません。 Cart クラスが書かれている時点では、そのオブジェクトの名前が後で $cart になるのか $another_cart になるのか、 それとも別のものになるのかはわかりません。 つまり、Cart クラスの中では $cart->items と書くことはできないのです。代わりに、 クラスの中からそのクラス内の関数や変数にアクセスするために、 疑似変数 $this を使用することが可能です。 $this は、「自分自身の」または「カレントのオブジェクト」 と読み変えることができます。つまり、 ' $this->items[$artnr] += $num ' は、 「同じクラス内の配列 items の $artnr カウンタに $num を追加する」または「カレントオブジェクト内の配列 items の $artnr カウンタに $num を追加する」と読み変えることが可能です。

注意: 擬似変数 $this は、メソッドが静的にコールされた場合に 常に定義されるわけではありません。しかし、はっきりしていることは: もしメソッドが別のオブジェクトから静的にコールされている場合は $this が定義されるということです。 この場合、 $this は呼び出し元のオブジェクトとなります。 これを説明したのが次の例です:

<?php
class A
{
    function
foo ()
    {
        if (isset(
$this )) {
            echo
'$this is defined (' ;
            echo
get_class ( $this );
            echo
")\n" ;
        } else {
            echo
"\$this is not defined.\n" ;
        }
    }
}

class
B
{
    function
bar ()
    {
        
A :: foo ();
    }
}

$a = new A ();
$a -> foo ();
A :: foo ();
$b = new B ();
$b -> bar ();
B :: bar ();
?>

上の例の出力は以下となります。

$this is defined (a) $this is not defined. $this is defined (b) $this is not defined.

注意: クラスとオブジェクトを処理する優れた関数がいくつかあります。 クラス/オブジェクト関数 をざっとみてみると良いでしょう。