私は、オブジェクトの種類を本当に気にせずに、オブジェクトで使用することを意図したコードに取り組んできました。作成中のメソッドが任意の型のオブジェクトを期待しているというヒントを入力したかったのですが、問題が発生しました。
私はfunction myFunc (object $obj)
とfunction myFunc (stdClass $obj)
を試しましたが、オブジェクトを渡そうとしたときにこれらのエラーの両方が生成されました:
キャッチ可能な致命的なエラー:MyClass :: MyFunc()に渡される引数1はオブジェクトのインスタンスでなければなりません。指定されたObjectActualClassのインスタンスです
同じことがstdClass
でも起こりました
何が欠けていますか? stdClass
から継承された別のクラスを明示的に継承しなかったすべてのクラスは、PHPのすべてのクラスの基本クラスがstdClass
になることを意味します。これはそうではありませんか?
stdClassは基本クラスではありません! PHPクラスは自動的にどのクラスからも継承しません。明示的に別のクラスを拡張しない限り、すべてのクラスはスタンドアロンです。PHPこれは多くのオブジェクト指向言語とは異なります尊敬。
これを強制する最良の方法は、Object
という縮退したインターフェイスを作成することです。縮退インターフェースとは、定義されたメソッドがないことを意味します。
interface Object {
// leave blank
}
次に、基本クラスでObject
を実装できます。
class SomeBase implements Object {
// your implementation
}
これで、必要に応じて関数を呼び出すことができます
function myFunc (Object $obj);
myFunc($someBase);
Object
インターフェースから継承するオブジェクトを渡すと、この型のヒントが渡されます。配列、int、stringなどを渡すと、タイプヒントは失敗します。
まあそれは8年しかかかりませんでしたが、これはすぐに可能になるでしょう:PHP 7.2はobject
型のヒントを導入します! 私がこれを書いているように、それは現在RFCの段階にあり、 11月にリリースされる予定です です。
11月30日更新:PHP 7.2がリリースされました
これは期待通りに動作します:
<?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の既存のソリューションが 壊れた の上に描画されます。幸い、それを修正するためにあなたがしなければならないすべては、インターフェースを削除することです。
オブジェクトには型のヒントはありませんが、次のものを使用できます。
if (!is_object($arg)) {
return;
}
すべてのオブジェクトが拡張する基本クラスはありません。タイプヒントを削除し、@param
アノテーションに期待されるタイプを文書化するだけです。
インターフェイスのすべてのユーザーが指定されたクラスを拡張する必要がない限り、これを行う組み込みのメカニズムはありません。しかし、なぜこれをとにかくしたいのですか?すべてのオブジェクトタイプには、APIに適切な入力を行うのに十分な共通点がありますか?
このようなヒントを入力できても、おそらく何も得られません。一方、インターフェイスを実装するためのパラメータのヒント(Traversable
など)を入力することは、はるかに意味があります。
タイプヒンティングに似たものが必要な場合は、実行時のチェックをパラメーターのis_object
に置き換えることが最善の方法です。
PHP 7.2以降、この機能は実装されています。ここで、任意のオブジェクトのヒントを入力できます。
function myFunc(Object $myObject) : Object {
return $myObject;
}
これは 公式ドキュメント で確認できます。
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で定義する必要があります