PHP7: scalar hinting
Продолжаю потихоньку наблюдать за развитием ПХП 7. Сегодня с утра выписывал из репозитория и компилировал новую версию, заметил, что в языке появилось указание типов для скаляров — поддерживаются int, float, string и bool.
Выглядит всё довольно естественно:
<?php
class Test
{
public function __toString()
{
return "test";
}
}
function len(string $a): int {
return strlen($a);
}
echo len(new Test);
echo len(new stdClass); // Fatal error: Argument 1 passed to len() must be of the type string, object given
В данном случае первый вызов ошибку не вызовет (в отличие от второго), так как у объекта есть магический метод __toString, который вызывается, когда объект требуется привести к строке, так что всё логично. Возможные преобразования описаны в документации и ничего нового там нет, всё в соответствии с текущей логикой языка.
Есть и второй режим работы — строгий. Его можно включить при помощи конструкции declare, которая должна быть первой конструкцией языка (теперь у неё приоритет даже над namespace) в файле:
<?php
declare(strict_types=1);
namespace Test;
class Test
{
public function __toString()
{
return "test";
}
}
function len(string $a): int {
return strlen($a);
}
echo len(new Test); // Fatal error: Argument 1 passed to Test\len() must be of the type string, object given
В этом случае все проверки на тип становятся строгими и никаких неявных преобразований не допускается.
По правде говоря, мне больше импонирует второй режим — несколько лет программирования на «Гоу» и «Пайтоне» позволили оценить все прелести строгой типизации, но существующий код большого продукта привести за приемлемое к строгому режиму будет часто невозможно, на мой взгляд. Видимо поэтому создатели языка ограничили действие строгого режима рамками файла — новые части можно писать, не затрагивая поведение старых, это удобно.
Мне не нравится необходимость использовать declare() везде. Я бы предпочел, что бы определенное поведение можно было бы включить из php.ini, например.
Опять-таки, всплывает вопрос перегрузки методов, который есть в языках со строгой типизацией параметров.
Комментарий для Олег Горбунов:
Возможно, ещё сделают это, сейчас сделано по RFC v0.5, а текущая — 0.5.3, он ещё развивается.
Такого, увы, нет. Но я бы предпочёл генерики, а не перегрузку.
Какой странный синакс у declare, нигде в языке больше такого нет. Больше ожидаемо было бы что то типа declare([’strict’ => true])
Комментарий для alexei:
Почему ожидаемо? declare не функция, а конструкция. Причём древняя, примеры её использования:
declare(ticks=100);
declare(encoding=’ISO-8859-1’);
параметры у неё строго определённые и должны анализироваться во время синтаксического анализа, а не интерпретации. Отсюда и синтаксис.
Комментарий для Евгения Степанищева:
Кое-кому еще тоже навеяло: https://github.com/ircmaxell/PhpGenerics =)
Комментарий для Олег Горбунов:
Мать моя… :) Восхищён крутостью изврата! :)