web-dev-qa-db-ja.com

任意のオブジェクトのタイプヒント

私は、オブジェクトの種類を本当に気にせずに、オブジェクトで使用することを意図したコードに取り組んできました。作成中のメソッドが任意の型のオブジェクトを期待しているというヒントを入力したかったのですが、問題が発生しました。

私はfunction myFunc (object $obj)function myFunc (stdClass $obj)を試しましたが、オブジェクトを渡そうとしたときにこれらのエラーの両方が生成されました:

キャッチ可能な致命的なエラー:MyClass :: MyFunc()に渡される引数1はオブジェクトのインスタンスでなければなりません。指定されたObjectActualClassのインスタンスです

同じことがstdClassでも起こりました

何が欠けていますか? stdClassから継承された別のクラスを明示的に継承しなかったすべてのクラスは、PHPのすべてのクラスの基本クラスがstdClassになることを意味します。これはそうではありませんか?

49
GordonM

stdClassは基本クラスではありません! PHPクラスは自動的にどのクラスからも継承しません。明示的に別のクラスを拡張しない限り、すべてのクラスはスタンドアロンです。PHPこれは多くのオブジェクト指向言語とは異なります尊敬。

46
Abdullah

これを強制する最良の方法は、Objectという縮退したインターフェイスを作成することです。縮退インターフェースとは、定義されたメソッドがないことを意味します。

interface Object {

   // leave blank

}

次に、基本クラスでObjectを実装できます。

class SomeBase implements Object {

   // your implementation

}

これで、必要に応じて関数を呼び出すことができます

function myFunc (Object $obj);

myFunc($someBase);

Objectインターフェースから継承するオブジェクトを渡すと、この型のヒントが渡されます。配列、int、stringなどを渡すと、タイプヒントは失敗します。

36
Gaz_Edge

まあそれは8年しかかかりませんでしたが、これはすぐに可能になるでしょう:PHP 7.2はobject型のヒントを導入します! 私がこれを書いているように、それは現在RFCの段階にあり、 11月にリリースされる予定です です。

11月30日更新:PHP 7.2がリリースされました

RFC:オブジェクトタイプヒント

ディスカッション

これは期待通りに動作します:

<?php

class Foo {}
class Bar {}

function takeObject(object $obj) {
    var_dump(get_class($obj));
}

takeObject(new Foo);
takeObject(new Bar);
takeObject('not an object');

結果は:

string(3)「フー」

string(3)「バー」

致命的なエラー:キャッチされないTypeError:takeObject()に渡される引数1は、オブジェクト、文字列が指定され、呼び出される必要があります...

https://3v4l.org/Svuij を参照してください

これの1つの副作用は objectが予約語になった です。これにより、残念ながら@ -Gaz_Edgeの既存のソリューションが 壊れた の上に描画されます。幸い、それを修正するためにあなたがしなければならないすべては、インターフェースを削除することです。

12
iainn

オブジェクトには型のヒントはありませんが、次のものを使用できます。

if (!is_object($arg)) {
    return;
}
11
Ben

すべてのオブジェクトが拡張する基本クラスはありません。タイプヒントを削除し、@paramアノテーションに期待されるタイプを文書化するだけです。

7
NikiC

インターフェイスのすべてのユーザーが指定されたクラスを拡張する必要がない限り、これを行う組み込みのメカニズムはありません。しかし、なぜこれをとにかくしたいのですか?すべてのオブジェクトタイプには、APIに適切な入力を行うのに十分な共通点がありますか?

このようなヒントを入力できても、おそらく何も得られません。一方、インターフェイスを実装するためのパラメータのヒント(Traversableなど)を入力することは、はるかに意味があります。

タイプヒンティングに似たものが必要な場合は、実行時のチェックをパラメーターのis_objectに置き換えることが最善の方法です。

3
Jon

PHP 7.2以降、この機能は実装されています。ここで、任意のオブジェクトのヒントを入力できます。

function myFunc(Object $myObject) : Object {
    return $myObject;
}

これは 公式ドキュメント で確認できます。

2
Ophidian

stdClassのTypehintはPHP 5.3+(私が間違っていない場合)から機能します。以下はstdClass構成のtypehintを使用した有効なコードです。

test.php

class Test{
    function hello(stdClass $o){
        echo $o->name;
    }
}

class Arg2 extends stdClass{
    public $name = 'John';
    function sayHello(){
        echo 'Hello world!';
    }
}

$Arg1 = new stdClass();
$Arg1->name = 'Peter';

$Arg2 = new Arg2();
$Arg2->sayHello();

$test = new Test();

// OK
$test->hello($Arg1);
$test->hello($Arg2);

// fails
$test->hello(1);

プリントアウト:

こんにちは世界!
ピーター
ジョン

キャッチ可能な致命的なエラー:Test :: hello()に渡される引数1は、stdClassのインスタンスであり、整数を指定し、32行目のtest.phpで呼び出し、5行目のtest.phpで定義する必要があります

1
lubosdz