PHP7から、関数の返り値のタイプヒントが書けるようになりました。返り値のタイプヒントは関数の引数リストの後ろに: [型名]
で指定します。
<?php
function foo(): array {
return [1,2,3];
}
foo();
上の例では、foo関数の返り値の型をarrayとして宣言しています。
型が合っていない場合、引数のタイプヒント同様に怒られます。
PHP Fatal error: Uncaught TypeException: Return value of foo() must be of the type array, integer returned in /tmp/foo.php on line 3 in /tmp/foo.php:3
Stack trace:
#0 /tmp/foo.php(5): foo()
#1 {main}
thrown in /tmp/foo.php on line 3
また、PHP7からはスカラ型(int, float, bool, string)のタイプヒントがサポートされましたので、返り値についてもスカラ型を指定できます。
クラスメソッドの場合
上では関数を例に出しましたが、クラスのメソッドでも同じように返り値のタイプヒントが使えます。また、インターフェースを実装したりクラス継承したりする場合、子の返り値のタイプヒントは親メソッド(またはインターフェース宣言)と合わせる必要があります。
<?php
interface Foo {
static function now(): DateTime;
}
class Bar implements Foo {
static function now(): DateTime {
return new DateTime();
}
}
Bar::now();
これはフレームワークなどで活用されてはじめて真価を発揮するような機能だと思いますが、PHP5系のサポートを切らないとフレームワークでは採用できないので、まだまだ道のりは長そうですね。
型宣言の位置、変だよね?
PHPはCに似た文法の言語だと思っていたのに、返り値のタイプヒントを関数の前に書けないのは意外といえば意外ですよね。
RFCには、Hack, Haskell, Go, Erlang, ActionScript, TypeScript が引数より後ろで返り値の型宣言するよね、と書いてあります。Hackに合わせること自体は合理的な判断だと思うので、慣れていくしかないでしょう。
引き合いに出す言語としてHaskellはどう考えても不適切(文法自体を型つきラムダ計算から輸入しているので、順番をいじると意味が無くなる)ですが、広い心でスルーしましょう。
ちょっぴり気になること
文法的に、ジェネレータ関数がyieldする型やreturnする型は書けないようです。この辺、Pythonだとどうなってるんですかね…?
<?php
/* foo()はジェネレータを返すので、これ自体は正しい */
function foo(): Traversable {
yield 1; /* yieldする型を記述する方法が無い気がする */
}
foreach (foo() as $v) {
var_dump($v);
}