PHP で間違った型を使用しないようにするにはどうすればよいですか?
-
02-07-2019 - |
質問
ご存知のとおり、PHP は非常に緩やかに型付けされています。この言語では、関数パラメーターやクラス変数にいかなる種類の型も指定する必要はありません。これは強力な機能となる可能性があります。
ただし、スクリプトのデバッグが苦痛になる場合もあります。たとえば、ある種類のオブジェクトを、別の種類のオブジェクトを期待するメソッドに渡すと、渡されたオブジェクトに特定の変数/メソッドが存在しないというエラー メッセージが生成されることがあります。こうした状況はほとんどが迷惑です。さらに厄介な問題は、あるオブジェクトを間違ったクラスのオブジェクトで初期化し、その「間違ったオブジェクト」がスクリプトの実行の後半まで使用されない場合です。この場合、元の引数を渡したときよりもかなり遅れてエラーが発生することになります。
渡したものに特定のメソッドや変数が含まれていないと文句を言ったり、渡したオブジェクトが使用されるまでスクリプト実行のずっと後まで待つのではなく、 むしろ、間違ったタイプのオブジェクトを指定した場所に、オブジェクトのタイプが正しくない、または互換性がないことを示すエラー メッセージが表示される方が望ましいと思います。
コード内でこのような状況をどのように処理しますか?互換性のない型をどのように検出しますか?エラー メッセージをより簡単に理解できるように、スクリプトに型チェックを導入するにはどうすればよいですか?
また、Php で継承を考慮しながらこれらすべてを行うにはどうすればよいでしょうか?考慮する:
<?php
class InterfaceClass
{
#...
}
class UsesInterfaceClass
{
function SetObject(&$obj)
{
// What do I put here to make sure that $obj either
// is of type InterfaceObject or inherits from it
}
}
?>
次に、このコードのユーザーは、独自の具象クラスを使用してインターフェイスを実装します。
<?php
class ConcreteClass extends InterfaceClass
{
}
?>
ConcreteClass インスタンスと、今後のすべての不明なユーザー定義オブジェクトも SetObject で受け入れられるようにしたいと考えています。正しい型をチェックする際にこれを許可するにはどうすればよいでしょうか?
解決
実際には、クラスについては、PHP(5+)で型ヒントを提供できます。
<?php
class UsesBaseClass
{
function SetObject(InterfaceObject $obj)
{
}
}
?>
これは、期待どおりに継承でも正しく機能します。
余談ですが、クラス名に「オブジェクト」という言葉を入れないでください...
他のヒント
Eran Galperinの応答に加えて、特定のクラスのオブジェクトだけでなく、パラメータを配列にするように型ヒントを使用することもできます。
<?php
class MyCoolClass {
public function passMeAnArray(array $array = array()) {
// do something with the array
}
}
?>
ご覧のとおり、 :: passMeAnArray()
メソッドは array
を期待するというヒントを入力でき、メソッドがwと呼ばれる場合のデフォルト値を提供します/ oパラメータ。
プリミティブ型の場合、is_ *関数も使用できます:
public function Add($a, $b)
{
if (!is_int($a) || !is_int($b))
throw new InvalidArgumentException();
return $a + $b;
}
おわかりのように、タイプヒンティングについては複数の回答があります。これは技術的な解決策です。しかし、設計全体が賢明で直感的であることも確認する必要があります。これにより、タイプの問題やミスがより少なくなります。
これらのタイプの障害でさえ、実行時にスローされることに注意してください。コードのテストがあることを確認してください。
記述した場合でも、スクリプトはクラッシュし、オブジェクトYにメソッド/属性Xがないため、どこから来たのかがわかります。
とにかく、メソッドに間違ったオブジェクトを渡すために成長したプログラマーを常に防ぐことは良い時間の投資ではないと思います:代わりに文書化とトレーニングにそれを使うことができます。
ダックタイピングと慎重な同僚が必要であり、アプリをより厳格にする追加のチェックではありません。
しかし、それはPythonistaの視点かもしれません...
php.iniファイルでerror_reporting ini設定を設定するか、error_reporting関数を使用して実行時に設定できます