Пишу, по большей части, про историю, свою жизнь и немного про программирование.

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

В этом случае все проверки на тип становятся строгими и никаких неявных преобразований не допускается.

По правде говоря, мне больше импонирует второй режим — несколько лет программирования на «Гоу» и «Пайтоне» позволили оценить все прелести строгой типизации, но существующий код большого продукта привести за приемлемое к строгому режиму будет часто невозможно, на мой взгляд. Видимо поэтому создатели языка ограничили действие строгого режима рамками файла — новые части можно писать, не затрагивая поведение старых, это удобно.

6 комментариев
Олег Горбунов 2015

Мне не нравится необходимость использовать declare() везде. Я бы предпочел, что бы определенное поведение можно было бы включить из php.ini, например.
Опять-таки, всплывает вопрос перегрузки методов, который есть в языках со строгой типизацией параметров.

Евгений Степанищев (bolknote.ru) 2015

Комментарий для Олег Горбунов:

Мне не нравится необходимость использовать declare() везде. Я бы предпочел, что бы определенное поведение можно было бы включить из php.ini, например.

Возможно, ещё сделают это, сейчас сделано по RFC v0.5, а текущая — 0.5.3, он ещё развивается.

Опять-таки, всплывает вопрос перегрузки методов, который есть в языках со строгой типизацией параметров.

Такого, увы, нет. Но я бы предпочёл генерики, а не перегрузку.

alexei 2015

Какой странный синакс у declare, нигде в языке больше такого нет. Больше ожидаемо было бы что то типа declare([’strict’ => true])

Евгений Степанищев (bolknote.ru) 2015

Комментарий для alexei:

Почему ожидаемо? declare не функция, а конструкция. Причём древняя, примеры её использования:

declare(ticks=100);
declare(encoding=’ISO-8859-1’);

параметры у неё строго определённые и должны анализироваться во время синтаксического анализа, а не интерпретации. Отсюда и синтаксис.

Олег Горбунов 2015

Комментарий для Евгения Степанищева:

Кое-кому еще тоже навеяло: https://github.com/ircmaxell/PhpGenerics =)

Евгений Степанищев (bolknote.ru) 2015

Комментарий для Олег Горбунов:

Мать моя… :) Восхищён крутостью изврата! :)