あるオブジェクトが指定インターフェースをimplementsしているかどうかの条件判定について

投稿者: Anonymous

具体的には、ArrayAccess インターフェイスを「implementsしているかどうか」条件判定したい


Q1
調べたら2つ見つかり、試したら何れも期待した通り動作したのですが、違いは何ですか?
何れを使用した方が良い、とかありますか?

is_subclass_of
instanceof

Q2
また、下記も見つかったのですが、これはまた違う話ですか?

ReflectionClass::isSubclassOf

解決

要求される内容に関しては、正常時はどちらも動作に違いが無いでしょう。

おそらく、推奨は instanceof だと思われます。

is_subclass_of()は、クラスが存在しなかった場合のオートローダー呼び出しや脆弱性懸念があり、
ReflectionClass::isSubclassOf()は、調査対象オブジェクトをそのまま使えないだろうからです。

仕様やWebから読み取れる特徴は以下になります。

  • is_subclass_of()

    • クラス/オブジェクト関数である
    • 第1パラメータに「オブジェクトのインスタンス」だけではなく「クラス名文字列」も指定可能
      オプショナルなパラメータでクラス名指定を off に出来る
    • 名前の通り「サブクラス」であるかの判定であり、「上位のクラス」に第2パラメータのクラス/インターフェースが存在するかどうかを判定する
    • 第2パラメータに第1パラメータのオブジェクトと同じクラスを指定すると false が返る
    • 存在しない未知のクラスの場合、登録されたオートローダーが呼ばれる
    • 参考に get_class(), get_parent_class(), is_a(), class_parents() がある
    • Ver 5.3.6 以前はインタフェースを実装したクラスそのものでは結果が false で返っていた
      そこからさらにサブクラスになれば true が返った
    • 類似の is_a 関数では、上記仕様変更の影響で、5.3.7, 5.3.8 に脆弱性バグがある
      PHPのis_a関数における任意のコードを実行される脆弱性(CVE-2011-3379)とは何だったか
  • instanceof

    • 型演算子(二項演算子)である
    • あるPHP変数が特定のクラスのインスタンスまたはインターフェースの実装であるかどうかを調べるもの。通常はクラス名のリテラルを指定するが、別のオブジェクトや文字列変数も使用可能
    • 指定したPHP変数がオブジェクトでは無くても、結果が false になるだけでエラーにはならない
      ただし定数はエラーになる
    • Ver 5.1.0 以前は、上記 is_subclass_of と同じく、存在しない未知のクラスの場合、登録されたオートローダーが呼ばれる
      さらに、クラスが読み込めなかった場合に致命的なエラーが発生していた
    • 参考に get_class(), is_a() がある
  • ReflectionClass::isSubclassOf()

    • ReflectionClassのメソッドである
    • クラス名のリテラルを指定して ReflectionClass のオブジェクトを作ってから呼び出す
    • 指定したクラスを継承している、あるいは指定したインターフェイスを実装しているかどうかを調べる
    • is_subclass_of() 関数のサブセット的な機能
    • 参考に ReflectionClass::isInterface(), ReflectionClass::implementsInterface(), is_subclass_of(), get_parent_class() がある
    • ReflectionClass そのものは、プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術
      PHPでリフレクション
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *