Kimita / mobpair_with_mohira

モブプロ・ペアプロ初挑戦!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rankコンストラクタのガード条件に該当する状態は理論上ありえないの不要

suin opened this issue · comments

commented

public function __construct(string $val)
{
if (false === is_string($val)) {
throw new \TypeError();
}
$this->val = $val;
}

Rank:: __constructの第一引数はstringで型宣言されているので、false === is_string($val)で改めてチェックする必要がないですね。

ご指摘ありがとうございます!
実はこのガード条件、コンストラクタ第一引数の型宣言を無くすつもりで追加したコードだったのですが、第一引数の型宣言を除去し忘れてコミットしてました。

ちなみに「第一引数の型宣言を無くそう」と考えたのは、下記のページの表で示されているような暗黙キャストを回避したいという意図からです。
https://qiita.com/hnw/items/8631c99349509c504d35#スカラ型のタイプヒントと型キャスト

「第一引数の型をstringと指定しているんだから、boolean を渡したらタイプエラーになるよね」と期待して試しに true を渡してみたら、コケずに「1」がセットされてびっくりしたので、中でガード条件を書くことにしたのでした。

commented

@Kimita

プリミティブ型について自力でガード条件を書かなければならなかったのはPHP5までの時代の話で、declare(strict_types=1);をちゃんと書いて「強い型付け」にしていれば暗黙キャストは発生しませんので、PHP7からは型宣言をちゃんとしたほうがまっとうな気がします。

<?php

declare(strict_types=1);

function do_something(string $value): void
{
}

do_something('');
do_something(true); // Fatal error: Uncaught TypeError: Argument 1 passed to do_something() must be of the type string, boolean given, called in .../Untitled.php on line 10 and defined in .../Untitled.php:5

declare(strict_types=1);がない「弱い型付け」の場合にのみ暗黙の型変換が発生します:

<?php

//declare(strict_types=1);

function do_something(string $value): void
{
	var_dump($value);
}

do_something('');  //=> string(0) ""
do_something(true); //=> string(1) "1"

@suin
!!!!!
丁寧な解説のおかげで自分が何を見落としていたのかをやっと理解できました。

Rank を new する側で declare(strict_types=1); を書いてあげてなかったから、コンストラクタを呼んだ時に暗黙キャスト済みの値を引数へ渡しちゃってた、ということでした。

「試しに true を渡してみたらコケずに 1 がセットされてびっくり」に遭遇したのは、laravel の tinker を使って何気なく動作確認した時でした。
tinker起動してちゃんと declare(strict_types=1); を実行してからであれば、型を厳密に扱ってくれました。

$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.2.7 — cli) by Justin Hileman
>>> $hoge = new \App\Domain\Trump\Models\Vo\Rank('K');
=> App\Domain\Trump\Models\Vo\Rank {#2855}
>>> echo $hoge;
K⏎
>>> $hoge = new \App\Domain\Trump\Models\Vo\Rank(true);
=> App\Domain\Trump\Models\Vo\Rank {#2853}
>>> echo $hoge;
1⏎
>>> declare(strict_types = 1);
>>> $hoge = new \App\Domain\Trump\Models\Vo\Rank(true);
TypeError: Argument 1 passed to App/Domain/Trump/Models/Vo/Rank::__construct() must be of the type string, boolean given on line 2
>>> $hoge = new \App\Domain\Trump\Models\Vo\Rank('Q');
=> App\Domain\Trump\Models\Vo\Rank {#2859}
>>> echo $hoge;
Q⏎
>>> exit
Exit:  Goodbye

ありがとうございました!

本 issue は、当該ブランチを更新した時にcloseする予定です。