オーバーロード

メソッド呼び出しとメンバーへのアクセスのいずれについても、 __call, __get そして __set メソッドを通してオーバーロードすることができます。 オブジェクトや継承されたオブジェクトが アクセスしようとしているメンバーもしくはメソッドを含んでいない場合でも、 これらのメソッドは実行されます。 オーバーロードしている全てのメソッドは、 static として定義されていてはいけません。 オーバーロードしている全てのメソッドは public として定義されていなければなりません。

PHP 5.1.0 以降、__isset や __unset メソッドを通じて isset() 関数や unset() 関数を個々にオーバーロードする事も可能です。

メンバーのオーバーロード

void __set ( string name, mixed value )

mixed __get ( mixed name )

bool __isset ( string name )

void __unset ( string name )

独自のクラスで定義されているカスタムコードを実行するために、 特別な名前を持つメソッドによってクラスメンバーをオーバーロード することができます。 使用される $name パラメータは、 設定あるいは取得される変数名です。 __set() メソッドの $value パラメータにより オブジェクトが $name に設定する値を指定します。

例 19-20. __get, __set, __isset, __unset を使ったオーバーロードの例

<?php
class Setter
{
    
public $n ;
    
private $x = array( "a" => 1 , "b" => 2 , "c" => 3 );

    
public function __get ( $nm )
    {
        echo
"Getting [ $nm ]\n " ;

        if (isset(
$this -> x [ $nm ])) {
            
$r = $this -> x [ $nm ];
            print
"Returning: $r \n " ;
            return
$r ;
        } else {
            echo
"Nothing!\n" ;
        }
    }

    
public function __set ( $nm , $val )
    {
        echo
"Setting [ $nm ] to $val \n " ;

        if (isset(
$this -> x [ $nm ])) {
            
$this -> x [ $nm ] = $val ;
            echo
"OK!\n" ;
        } else {
            echo
"Not OK!\n" ;
        }
    }

    
public function __isset ( $nm )
    {
        echo
"Checking if $nm is set \n " ;

        return isset(
$this -> x [ $nm ]);
    }

    
public function __unset ( $nm )
    {
        echo
"Unsetting $nm \n " ;

        unset(
$this -> x [ $nm ]);
    }
}

$foo = new Setter ();
$foo -> n = 1 ;
$foo -> a = 100 ;
$foo -> a ++;
$foo -> z ++;

var_dump (isset( $foo -> a )); //true
unset( $foo -> a );
var_dump (isset( $foo -> a )); //false

// this doesn't pass through the __isset() method
// because 'n' is a public property
var_dump (isset( $foo -> n ));

var_dump ( $foo );
?>

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

Setting [a] to 100
OK!
Getting [a]
Returning: 100
Setting [a] to 101
OK!
Getting [z]
Nothing!
Setting [z] to 1
Not OK!

Checking if a is set
bool(true)
Unsetting a
Checking if a is set
bool(false)
bool(true)

object(Setter)#1 (2) {
  ["n"]=>
  int(1)
  ["x:private"]=>
  array(2) {
    ["b"]=>
    int(2)
    ["c"]=>
    int(3)
  }
}

メソッドのオーバーロード

mixed __call ( string name, array arguments )

特別なメソッド __call() を使用すると、存在しないメソッドの呼び出しを捕捉することができます。 つまり、__call() を使用すると、実際にコールされたメソッドの名前に応じた ユーザ定義の処理を実装することができるということです。 これは、たとえばプロキシを実装する場合などに便利です。 関数に渡された引数はパラメータ $arguments で受け取ることができ、 __call() メソッドの返り値が呼び出し元のメソッドの返り値となります。

例 19-21. __call を使ったオーバーロードの例

<?php
class Caller
{
    
private $x = array( 1 , 2 , 3 );

    
public function __call ( $m , $a )
    {
        print
"Method $m called: \n " ;
        
var_dump ( $a );
        return
$this -> x ;
    }
}

$foo = new Caller ();
$a = $foo -> test ( 1 , "2" , 3.4 , true );
var_dump ( $a );
?>

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

Method test called:
array(4) {
    [0]=>
    int(1)
    [1]=>
    string(1) "2"
    [2]=>
    float(3.4)
    [3]=>
    bool(true)
}
array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
}