2つの戻り値のいずれか-を返すことができるメソッドがいくつかあります(MCVを利用するフレームワークを使用しているため、特にこれらの少数の関数をリファクタリングすることは魅力的ではありません)
どちらか一方を返し、他で失敗する戻り値の型を宣言することは可能ですか?
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
現在のところ、サポートされている方法は、2つのオブジェクトがインターフェースを共有することです。例:
interface ReturnInterface {}
class FailObject implements ReturnInterface {}
class SuccessObject implements ReturnInterface {}
function test(): ReturnInterface {}
この例では、ReturnInterface
は空です。その単なる存在は、必要な戻り型宣言をサポートします。
現在、PHP internalsコミュニティは、ユニオン型について議論しています。 現在の提案が受け入れられた場合 、PHP 8+は複数の戻り値型をサポートします:
function test(): FailObject|SuccessObject {}
ただし、 以前のユニオンタイプRFC はdeclinedでした。
ユニオンの種類に関係なく、インターフェイスアプローチを好みます。私にとっては、より明確で拡張性があります。後でWarnObject
が必要な場合は、すべての署名を調べてFailObject|SuccessObject|WarnObject
に更新するのではなく、単にReturnInterface
を拡張するものとして定義する必要があります。
Bishopが指摘したように、複数の戻り値の型を追加するためのRFCがあります。ただし、PHP7.1の時点で、次のようにnull可能な戻り値の型を指定できるようになったと付け加えました。
function exampleFunction(string $input) : ?int
{
// Do something
}
したがって、この関数は文字列を受け取り、intの前に疑問符を追加することで、nullまたは整数を返すことができます。
ドキュメントへのリンクは次のとおりです。 http://php.net/manual/en/functions.returning-values.php
そして、そのページからの使用法を説明する引用があります:PHP 7.1では、型宣言の前に? —(たとえば、関数canReturnNullorString():?string)
また、これに関連する別のスレッドを次に示します。 PHP7のNullable戻り値型
7.2以降のPHPは、オブジェクトの戻り値の型をサポートします
http://php.net/manual/en/migration72.new-features.php
function test(object $obj) : object
// return any type of object ...
これは正しい方法ではありません:
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
複数の戻り値型は悪い習慣です。良い習慣:
例外を定義する必要があります。
class FailObjectException extends \Exception
{
private $exampleExtraInfo;
public function __construct($exampleExtraInfo, $message)
{
parent::__construct($message);
$this->exampleExtraInfo = $exampleExtraInfo;
}
public function exampleExtraInfo(): int
{
return $this->exampleExtraInfo;
}
}
これで、次のような関数を定義できます。
function test(): SucceedObject
{
if ($this->condition === false) {
throw new FailObjectException(...,...);
}
return SucceedObject;
}
そして、この関数をtry/catchで使用します:
try{
$succeedObject = $any->test();
} catch (FailObjectException $exception){
//do something
}