phpで実装上どうしてもタイトルのような事をしないといけなかったのでその方法のメモ。 そもそもの話、実装がまずいって事のような気がすご???くするんだけど、それは置いておこう。
前提
ふーむ? クラスBはクラスAから派生しててクラスBはクラスCを持っているとして、クラスBメソッド→クラスCメソッド→クラスBのインスタンスでクラスAメソッドを呼ぶってPHPだとできないよねーきっと #php
— サカサマのさめたすたす (@sharkpp) 2013, 11月 22
順に挙げると、
- クラスA と クラスB と クラスC があります。
- クラスB は クラスA を継承しています。
- クラスC は クラスA および クラスB とは関連がありません。
- この時、クラスC から クラスB のオブジェクトインスタンスを使い、クラスA のメソッドを呼び出すにはどうしたらよいだろうか?
- ただし、呼び出すメソッドは クラスB ですでにオーバーライドされていることする。
とりあえず、前提はこんな感じ。
ソースを載せると↓な感じ。
<?php
class C {
private $a;
function __construct($owner) { $this->a = $owner; }
public function test($v) {
// ここで $this->a を使い A::test を呼び出したい!
}
}
class A {
public function test($v) { return '!' . $v; }
}
class B extends A {
private $c;
function __construct() { $this->c = new C($this); }
public function test($v) { return $this->c->test($v); }
}
$b = new B;
echo $b->test('test') . "\n";
つまり、 クラスB::test() → クラスC::test() → クラスA::test() って感じで呼び出したい。
試行
色々ググってみる。
リフレクション使ったりとか、 (array)$hoge
したりで private
な、メンバ変数が取得出来たりとかアレなことをしていたりしてみた。
けど、ふと public
なメソッドなら call_user_func()
で呼び出せるんだから、クラス名付ければ呼び出せないか?と気が付いた。
やってみたら、すんなり行ってしまった。
解決
ふむふむ、call_user_func 使えば あるオブジェクトの親クラスを呼び出すことができるのか https://t.co/JSy3AsWVqT#php
— サカサマのさめたすたす (@sharkpp) 2013, 11月 22
該当部分だけ抜き出すと、
public function test($v) { // C::test()
return call_user_func(array($this->a, 'A::test'), $v);
}
って感じ。
クラス名は、 get_parent_class()
で取得してもいいかもしれない。
完全なソースは あるオブジェクトの親クラス(派生元クラス)のメソッドを外部から呼び出す - GitHub Gist に置きました。
実は、PHP: call_user_func - Manualのこのあたりにもさりげなく匂わせる感じでは書いてあったりしたけど、、、見落としていた。