Do You PHP?    
Search Engine Optimization  php5 powerd  Valid XHTML 1.0!  Valid CSS!  このサイトのはてなブックマーク数 



last updated
2004/10/09

counter hits
since 1999/11/06


PHP4のクラスとJavaのクラス - クラスメソッド・オブジェクトメソッドのいずれでコールされたかを判定する

caution[2004/03/21] PHP5.0.0RC1でエラーレベル「E_STRICT」を含めた場合、非staticメソッドをstaticに呼び出そうとすると、「Strict Standards: Non-static method ClassA::check() should not be called statically」のようなワーニングが表示されます 。エラーレベル「E_ALL」では表示されません

PHP4からオブジェクト指向的な機能・動作が改善されていますが、オブジェクト指向言語であるJavaとどの程度挙動が異なるか、ちょっとずつまとめてみようかと思います。基本的には、PHPマニュアルに記載されていなくて、「どうなるの?」と思ったことを主にやっています。

今回はPHP-usersから、「クラスメソッド・オブジェクトメソッドのいずれでコールされたかを判定する」についてです。

PHP4ではクラスメソッドとして呼び出す場合、「Class::method()」としますが、呼び出されたクラス側でクラスメソッド・オブジェクトメソッドのいずれでコールされたのかを判定したい場合があります。

この場合、当該メソッド内で


<?php
        :
    isset($this)
        :
?>

を使用し、そのクラスのインスタンスが存在しているかどうか(変数「$this」にセットされているかどうか)をチェックすることで、*とりあえず*判定することが可能です。

●[PHP-users 9185] Re: クラス関数とオブジェクト関数で同一名を使うには? より

<?php
class ClassA {
   // クラス関数で呼ばれたか、オブジェクト関数で呼ばれたか?
   function check() {
     return isset($this)?'オブジェクト':'クラス';
   }
}

echo ClassA::check();
$obj = new ClassA;
echo $obj->check();
?>

ここで、「他のクラス内からコールされた場合」を試してみると、(残念ながら)ちょっと話が違ってきます。。。

●他のクラス内からコールするサンプル

<?php
class ClassA
{
  /**
   * クラスメソッド/オブジェクトメソッドのいずれでコール
   * されたかを返す
   */
  function check() {
    return isset($this) ? 'オブジェクト' : 'クラス';
  }
}

class ClassB
{
  /**
   * ClassAをクラスメソッドとしてコール
   */
  function check() {
    return ClassA::check();
  }

  /**
   * ClassAをオブジェクトメソッドとしてコール
   */
  function check2() {
    $a = new ClassA();
    return $a->check();
  }
}

/**
 * ClassA単独をクラスメソッド・オブジェクトメソッドとしてコール
 */
echo '●ClassA単独をクラスメソッド・オブジェクトメソッドとしてコール<br>';
echo 'ClassA::check()='.ClassA::check().'<br>';
$obj = new ClassA;
echo '$obj->check()='.$obj->check().'<br>';
echo '<hr>';

/**
 * ClassBのメソッドをクラスメソッドとしてコール
 */
echo '●ClassBのメソッドをクラスメソッドとしてコール<br>';
echo 'ClassB::check()='.ClassB::check().'<br>';
echo 'ClassB::check2()='.ClassB::check2().'<br>';
echo '<hr>';

/**
 * ClassBのメソッドをオブジェクトメソッドとしてコール
 */
echo '●ClassBのメソッドをオブジェクトメソッドとしてコール<br>';
$obj_b = new ClassB;
echo '$obj_b->check()='.$obj_b->check().'<br>';
echo '$obj_b->check2()='.$obj_b->check2().'<br>';
?>

●出力結果
●ClassA単独をクラスメソッド・オブジェクトメソッドとしてコール
ClassA::check()=クラス
$obj->check()=オブジェクト
●ClassBのメソッドをクラスメソッドとしてコール
ClassB::check()=クラス
ClassB::check2()=オブジェクト
●ClassBのメソッドをオブジェクトメソッドとしてコール
$obj_b->check()=オブジェクト
$obj_b->check2()=オブジェクト

上記はPHP4.3.3で試した結果ですが、

  • オブジェクトメソッドとしてコールする場合は問題なし
  • あるクラスをクラスメソッド・オブジェクトメソッドとして別クラス外からコールする場合は問題なし
  • あるクラスを別クラスからコールする場合、別クラスもクラスメソッドとしてコールする場合は問題なし
  • あるクラスを別クラスからコールする場合、別クラスをインスタンス化してコールする場合は問題あり

のようです(この結果は、実際にはisset($this)の動作の結果ですが。。。)。なお、get_class($this)など別の判定基準を導入することである程度は精度を上げることが出来るようですが、完全には難しいようです。



About This Site |  Privacy Policy |  Contact
Copyright © 1999 - 2004 by Hideyuki SHIMOOKA all rights reserved.