アシアル株式会社主催 開発者向け、一歩先をいくためのテクニカルセミナー

<< POSTデータのシリアル化について 質問一覧 セッションの2次元配列 >>

  • 0P
親クラスのメソッドをクラス外から呼びたい

  1. class testClass{
  2.     private $a=1;
  3.   }
  4.   
  5.   class testClass2 extends testClass{
  6.     private $a=2;
  7.     
  8.     function get_a(){return $this->a;}
  9.   }
  10.   
  11.   class testClass3 extends testClass2{
  12.     private $a=3;
  13.     function get_a(){return $this->a;}
  14.   }
  15.   
  16.   $test=new testClass3();
  17.   
  18.   //testClass2::get_aを呼びたい
  19.   $ret=$test->get_a();

$ret=3になるのですが、testClass2の2を取得したいわけです。
testClass3でparent::get_aするなりtestClass2を直接インスタンス化すれば簡単なのですが、
クラス自体は触らずにどうにかする方法ってありませんでしょうか。

あとtestClass::$aもですが、これはrunkit_method_addでも使わないとどうにもならないかな…



#全然関係ないけどtestClass3をvar_dumpすると↓みたいになってキモくないですか?
  1. object(testClass3)#1 (3) {
  2.   ["a:private"]=>
  3.   int(3)
  4.   ["a:private"]=>
  5.   int(2)
  6.   ["a:private"]=>
  7.   int(1)
  8. }

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。

Q親クラスのメソッドをクラス外から呼びたい NurseAngel  [12月16日 13時28分] 
┣(削除済み)
┣参考になったRe:親クラスのメソッドをクラス外から呼びたい yakou850  [12月16日 14時57分] 
┣参考になったRe:親クラスのメソッドをクラス外から呼びたい mgngmgng  [12月16日 14時58分] 
┣参考になったRe:親クラスのメソッドをクラス外から呼びたい kaitau  [12月16日 16時23分] 
┃┗満開Re:Re:親クラスのメソッドをクラス外から呼びたい kaitau  [12月16日 20時33分] 
┣Re:親クラスのメソッドをクラス外から呼びたい NurseAngel  [12月16日 23時52分] 
┗参考になったRe:親クラスのメソッドをクラス外から呼びたい signal  [12月16日 23時55分] 

コメント一覧

並び替え( ツリー順 / 投稿順[降順] / 投稿順[昇順]

(削除済み)

この意見は投稿者によって削除されました。

Re:親クラスのメソッドをクラス外から呼びたい

色々考えてみた上でなのですが・・・
クラスを書き換えたりtestClass2のインスタンスを作らないでというのは無理なんじゃないかと・・・。

Re:親クラスのメソッドをクラス外から呼びたい

キモいですが、一応取得できました(環境:WinXP PHP5.2.5)
testClass::$aは取れないですね...
# 外してたらスルーしてください

[追記]
あ..これ結局testClass2のインスタンス作ってるだけですね。
スルーでお願いします。

  1. <?php
  2. class testClass{
  3.   private $a=1;
  4. }
  5.  
  6. class testClass2 extends testClass{
  7.   private $a=2;
  8.   function get_a(){return $this->a;}
  9. }
  10.  
  11. class testClass3 extends testClass2 {
  12.   private $a=3;
  13.   function get_a(){return $this->a;}
  14. }
  15.  
  16.  
  17. $tc3=new testClass3();
  18. echo $tc3->get_a()// 3
  19.  
  20. // キモい...
  21. $parent=get_parent_class($tc3);
  22. $tc2=new $parent;
  23. echo $tc2->get_a()// 2

Re:親クラスのメソッドをクラス外から呼びたい

できた・・・orz

荒唐無稽なので、あまり出来る事にしたくないですけど、
常連の回答者さんなのでやむを得ない事情の上と信じて・・・

  1. <?php
  2.   $test=new testClass3();
  3.   $class = new ReflectionClass($test);
  4.  
  5.   $method=$class->getParentClass()->getMethod('get_a');
  6.   $ret = $method->invoke($test);
  7.   var_dump($ret);
  8. ?>

ちなみにprivateな変数 $a はさすがに無理っぽいです。

Re:Re:親クラスのメソッドをクラス外から呼びたい

どっかにあったよなぁ、と考えていたら、PHPUnitでのオブジェクトの
プロパティをassertするメソッドにそんな記述があった気がして、
そこを参考にしたらtestClassのprivateな$aが取れてしまいました。

  1. <?php
  2.  
  3. /**
  4.  * privateな属性の値を参照する。
  5.  * 参考: PHPUnit_Framework_Assert::getObjectAttribute($object, $attributeName)
  6.  */
  7. function get_private_value($obj,$attributeName,$class=false) {
  8.   if( $class===false) {
  9.     $class = get_class($obj);
  10.   }
  11.   $objArray = (array) $obj;
  12.   $privateName = sprintf("\0%s\0%s",$class,$attributeName);
  13.   if( array_key_exists($privateName,$objArray) ) {
  14.     return $objArray[$privateName];
  15.   }
  16.   return null;
  17.   
  18. }
  19.   $test=new testClass3();
  20.  
  21.   $ret = get_private_value($test,'a','testClass3');
  22.   var_dump($ret);
  23.   $ret = get_private_value($test,'a','testClass');
  24.   var_dump($ret);
  25.  
  26. ?>
もう、var_dumpのキモさなんか比較にならないんじゃないかってレベルですが。
object を array でキャストすると、objectのprivateやprotectedな
属性名の頭にnull文字(ASCII 0)などが付加された不思議なキーをもった配列が
とることができ・・・これで属性値を参照できます。
よくよく探すとマニュアルにも記載があり。
http://jp.php.net/manual/ja/language.types.array.php#language.types.array.casting

PHPUnitのこのソースを見た時は愕然としました・・。

Re:親クラスのメソッドをクラス外から呼びたい

皆様回答ありがとうございます。

クラスを触らずにどうにかしろとか言われたのですが、
やはりまともな方法では無理ですよね。

メソッド増やす方向で行きたいと思います。


testClass1::$aを拾うだけなら以下で出来ました。
が、普通の環境にrunkitとか入ってないしのう。
  1. $parent=get_parent_class('testClass3');
  2. $grand_parent=get_parent_class($parent);
  3.  
  4. runkit_method_add($grand_parent,'get_this_a','','return $this->a;');
  5. runkit_method_add($parent,'get_parent_a','','return $this->get_this_a();');
  6. runkit_method_add('testClass3','get_grand_parent_a','','return $this->get_parent_a();');
  7.  
  8. $tc3=new testClass3();
  9. $a=$tc3->get_grand_parent_a();



#配列にキャストとか思いつかねー
  1. $tc3_array=(array)$tc3;
  2. $a=$tc3_array["\0{$grand_parent}\0a"];
#簡単に取れてしまった…privateって何?

Re:親クラスのメソッドをクラス外から呼びたい

「そんなことわかってるよ」的な回答ですが・・・

力技でごり押さなければならないということは
設計自体に無理があるということだと思います。

こういう場合は継承するのではなくて親インスタンスを
内部に持つのがよいかもしれません。

  1. <?php
  2. class testClass {
  3.   private $a = 1;
  4.   public function get_a() { return $this->a}
  5. }
  6. class testClass2 {
  7.   private $a = 2;
  8.   public $parent;
  9.   public function __construct() {
  10.     $this->parent = new testClass;
  11.   }
  12.   public function get_a() { return $this->a}
  13. }
  14. class testClass3 {
  15.   private $a = 3;
  16.   public $parent;
  17.   public function __construct() {
  18.     $this->parent = new testClass2;
  19.   }
  20.   public function get_a() { return $this->a}
  21. }

---
確かに var_dump キモチワルイですね
こんなになるとは知りませんでした
POSTデータのシリアル化について 質問一覧 セッションの2次元配列