オーバーロード
PHP におけるオーバーロード機能は、 プロパティやメソッドを動的に “作成する” ための手法です。 これらの動的エンティティは、マジックメソッドを用いて処理されます。 マジックメソッドは、クラス内でさまざまなアクションに対して用意することができます。
オーバーロードメソッドが起動するのは、 宣言されていないプロパティやメソッドを操作しようとしたときです。 また、現在のスコープからは アクセス不能な プロパティやメソッドを操作しようとしたときにも起動します。 このセクションでは、これらの (宣言されていない、 あるいは現在のスコープからはアクセス不能な) プロパティやメソッドのことを “アクセス不能プロパティ” および “アクセス不能メソッド” と表記することにします。
オーバーロードメソッドは、すべて public
で定義しなければなりません。
注意:
これらのマジックメソッドの引数は、 参照渡し とすることはできません。
注意:
PHP における “オーバーロード” の解釈は、他の多くのオブジェクト指向言語とは異なります。 一般的に「オーバーロード」とは、 「名前は同じだけれども引数の数や型が異なるメソッドを複数用意できる」 という機能のことを指します。
変更履歴
バージョン | 説明 |
---|---|
5.3.0 | __callStatic() が追加されました。
public で、かつ static でない宣言を強制するような警告が追加されました。 |
5.1.0 | __isset() と __unset()
が追加されました。 __get() が private プロパティのオーバーロードに対応しました。 |
5.0.0 | __get() が追加されました。 |
プロパティのオーバーロード
public __set
( string $name
, mixed $value
) : void
public __get
( string $name
) : mixed
public __isset
( string $name
) : bool
public __unset
( string $name
) : void
__set() は、 アクセス不能(protected または private)または存在しないプロパティへデータを書き込む際に実行されます。
__get() は、 アクセス不能(protected または private)または存在しないプロパティからデータを読み込む際に使用します。
__isset() は、 isset() あるいは empty() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動します。
__unset() は、 unset() をアクセス不能(protected または private)または存在しないプロパティに対して実行したときに起動します。
引数 $name
は、
操作しようとしたプロパティの名前です。
__set() メソッドの引数
$value
は、
$name
に設定しようとした値となります。
プロパティのオーバーロードはオブジェクトのコンテキストでのみ動作します。
これらのマジックメソッドは、静的コンテキストでは起動しません。
したがって、これらのメソッドを
static
宣言してはいけません。
PHP 5.3.0 以降、マジックオーバーロードメソッドを static
宣言すると警告が発生します。
注意:
__set() の返り値は無視されます。 これは、PHP が代入演算子を処理する方法によるものです。 同様に __get() は、
$a = $obj->b = 8;のように代入と連結した場合には決してコールされません。
例1 __get()、 __set()、__isset() および __unset() メソッドを使ったプロパティのオーバーロードの例
<?phpclass PropertyTest{ /** オーバーロードされるデータの場所 */ private $data = array(); /** 宣言されているプロパティにはオーバーロードは起動しません */ public $declared = 1; /** クラスの外部からアクセスした場合にのみこれがオーバーロードされます */ private $hidden = 2; public function __set($name, $value) { echo "Setting '$name' to '$value'\n"; $this->data[$name] = $value; } public function __get($name) { echo "Getting '$name'\n"; if (array_key_exists($name, $this->data)) { return $this->data[$name]; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } /** PHP 5.1.0 以降 */ public function __isset($name) { echo "Is '$name' set?\n"; return isset($this->data[$name]); } /** PHP 5.1.0 以降 */ public function __unset($name) { echo "Unsetting '$name'\n"; unset($this->data[$name]); } /** マジックメソッドではありません。単なる例として示しています */ public function getHidden() { return $this->hidden; }}echo "<pre>\n";$obj = new PropertyTest;$obj->a = 1;echo $obj->a . "\n\n";var_dump(isset($obj->a));unset($obj->a);var_dump(isset($obj->a));echo "\n";echo $obj->declared . "\n\n";echo "Let's experiment with the private property named 'hidden':\n";echo "Privates are visible inside the class, so __get() not used...\n";echo $obj->getHidden() . "\n";echo "Privates not visible outside of class, so __get() is used...\n";echo $obj->hidden . "\n";?>
上の例の出力は以下となります。
Setting 'a' to '1' Getting 'a' 1 Is 'a' set? bool(true) Unsetting 'a' Is 'a' set? bool(false) 1 Let's experiment with the private property named 'hidden': Privates are visible inside the class, so __get() not used... 2 Privates not visible outside of class, so __get() is used... Getting 'hidden' Notice: Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29
メソッドのオーバーロード
public __call
( string $name
, array $arguments
) : mixed
public static __callStatic
( string $name
, array $arguments
) : mixed
__call() は、 アクセス不能メソッドをオブジェクトのコンテキストで実行したときに起動します。
__callStatic() は、 アクセス不能メソッドを静的コンテキストで実行したときに起動します。
引数 $name
は、
コールしようとしたメソッドの名前です。
引数 $arguments
は配列で、メソッド $name
に渡そうとしたパラメータが格納されます。
例2 __call() および __callStatic() メソッドによる、メソッドのオーバーロードの例
<?phpclass MethodTest{ public function __call($name, $arguments) { // 注意: $name は大文字小文字を区別します echo "Calling object method '$name' " . implode(', ', $arguments). "\n"; } /** PHP 5.3.0 以降 */ public static function __callStatic($name, $arguments) { // 注意: $name は大文字小文字を区別します echo "Calling static method '$name' " . implode(', ', $arguments). "\n"; }}$obj = new MethodTest;$obj->runTest('in object context');MethodTest::runTest('in static context'); // PHP 5.3.0 以降?>
上の例の出力は以下となります。
Calling object method 'runTest' in object context Calling static method 'runTest' in static context