HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

型宣言~int~

型宣言のint編。どこまで許容されるのか検証。

Main.php

<?php

function to_int($val):int {
    print "=== val=" . var_export($val, true) . " ===" . PHP_EOL;
    try {
        return $val;
    } catch (TypeError $e) {
        print $e->getMessage() . PHP_EOL;
        print $e->getTraceAsString() . PHP_EOL;
        return -1;
    }
}

class Hoge {
    private int $val;
    public function __construct($val) {
        $this->val = $val;
    }
}
class MyInteger {
    private int $val;
    public function __construct($val) {
        $this->val = $val;
    }
    public function __toString():string {
        return $this->val;
    }
}

var_dump(to_int(0));
var_dump(to_int(00));
var_dump(to_int(123));
var_dump(to_int(0123));
var_dump(to_int(0x123));
var_dump(to_int(0.1));
var_dump(to_int(1.23));
var_dump(to_int(false));
var_dump(to_int(true));
var_dump(to_int("0"));
var_dump(to_int("00"));
var_dump(to_int("123"));
var_dump(to_int("0123"));
var_dump(to_int("0x123"));
var_dump(to_int("hello"));
var_dump(to_int(null));
var_dump(to_int(new Hoge("123456789")));
var_dump(to_int(new MyInteger("123456789")));

実行結果。

$ php81 Main.php
=== val=0 ===
int(0)
=== val=0 ===
int(0)
=== val=123 ===
int(123)
=== val=83 ===
int(83)
=== val=291 ===
int(291)
=== val=0.1 ===
int(0)
=== val=1.23 ===
int(1)
=== val=false ===
int(0)
=== val=true ===
int(1)
=== val='0' ===
int(0)
=== val='00' ===
int(0)
=== val='123' ===
int(123)
=== val='0123' ===
int(123)
=== val='0x123' ===
to_int(): Return value must be of type int, string returned
#0 /home/hhelibex/blog/2022-0616-01/Main.php(43): to_int()
#1 {main}
int(-1)
=== val='hello' ===
to_int(): Return value must be of type int, string returned
#0 /home/hhelibex/blog/2022-0616-01/Main.php(44): to_int()
#1 {main}
int(-1)
=== val=NULL ===
to_int(): Return value must be of type int, null returned
#0 /home/hhelibex/blog/2022-0616-01/Main.php(45): to_int()
#1 {main}
int(-1)
=== val=Hoge::__set_state(array(
   'val' => 123456789,
)) ===
to_int(): Return value must be of type int, Hoge returned
#0 /home/hhelibex/blog/2022-0616-01/Main.php(46): to_int()
#1 {main}
int(-1)
=== val=MyInteger::__set_state(array(
   'val' => 123456789,
)) ===
to_int(): Return value must be of type int, MyInteger returned
#0 /home/hhelibex/blog/2022-0616-01/Main.php(47): to_int()
#1 {main}
int(-1)
$ 

最後のMyIntegerクラスは、ワンチャン __toString() が呼び出されて変換されたりしないかなと思ったりしたけどそんなわけはなかった。

ここで注意すべきなのは、あくまでも「:int」であり「:integer」とは書けないということ。 マニュアルに以下の記述がある。

警告 上記のスカラー型のエイリアスはサポートされていません。 つまり、これらはクラスやインターフェイスの名前として扱われているということです。 たとえば、型の宣言に boolean を使った場合、 値が boolean クラスまたはインターフェイスインスタンスであることが要求されます。 bool 型ではありません。

もし「:integer」と書いた場合、実行結果は以下のようになる。

PHP Warning:  "integer" will be interpreted as a class name. Did you mean "int"? Write "\integer" to suppress this warning in /home/hhelibex/blog/2022-0616-01/Main.php on line 3
=== val=0 ===
to_int(): Return value must be of type integer, int returned
#0 /home/hhelibex/blog/2022-0616-01/Main.php(30): to_int()
#1 {main}
PHP Fatal error:  Uncaught TypeError: to_int(): Return value must be of type integer, int returned in /home/hhelibex/blog/2022-0616-01/Main.php:10
Stack trace:
#0 /home/hhelibex/blog/2022-0616-01/Main.php(30): to_int()
#1 {main}
  thrown in /home/hhelibex/blog/2022-0616-01/Main.php on line 10