Тайпхинтинг в объявлении аргументов функции. И это таки тайпхинт, а не тупое насильное преобразование string -> int. Поскольку функция объявлена со скалярным тайпхинтом,
function foo(int $bar)
{
}
, то тогда в неё нельзя передать значение, которое не конвертируется в int строгим образом. Т.е. foo(«abc») приведёт к TypeError. Таким образом да, это таки тайпхинт, а не приведение к int.
Я замеряю время, которое тратится на отработку функции целиком, а не только её вызова.
Суть в том, что при наличии скалярного тайпхинта, значение аргумент будет преобразовано в требуемый строгим образом и далее это может привести к ускорению кода внутри функции поскольку в этом случае исчезает type juggling.
Скалярный тайпхинт таки отличается от приведения типа тем, что при тайпхинте значение аргумента не будет насильно приводится к требуемому.
Например, при вышеописанном объявлении функции корректными будут вызовы: foo(123), foo("123"), foo("12.3e1") (последние 2 допустимы, если не указан declare(strict_types=1)), но некорректными (при которых будет выброшено исключение): foo(null), foo("123abc") (внезапно!), foo("abc"), foo([]), foo(new stdClass),…
В то же время если заменить скалярный тайпхинт на приведение типа перед циклом, то тогда все перечисленные выше варианты станут а) допустимыми, б) приведение типа отработает во всех случаях.
Вы либо невнимательно читали, либо неправильно поняли. Скалярный тайпхинт может приводить к ускорению кода так как при использовании оного уменьшается количество неявных приведений типов.
Верно. Высосан из пальца, потому что это синтетический пример, о чём было сказано в начале.
Я хотел показать каким образом скалярный тайпхинт может привести к ускорению. В конце ответа я написал: «код может ускорится при использовании скалярных тайпхинтов, но в среднем общая производительность останется такой же».
Разумеется синтетика имеет мало общего с реальным приложением в продакшене.
Оно как раз не нарушает LSP. Поскольку, применительно к ООП LSP говорит о том, что субтип (дочерний класс) должен расширять родительский класс (интерфейс).
Представим, что есть базовый класс:
class Parent
{
/** @param string|int $bar */
public function foo($bar)
{
...
}
}
Согласно «контракту» метод foo должен принимать на вход аргумент строкового или целочисленного типа.
Тут мы говорим о том, что на вход должен поступить объект, являющийся инстансом класса Parent, и в метод foo этого объект мы передаём аргумент. Так как контракт метода foo говорит о том, что на вход должен поступить либо строковой либо целочисленный аргумент, то и переменная $arg тоже должна быть либо строкового, либо целочисленного типа.
Тут всё логично.
Теперь представим, что есть класс
class Child extends Parent
{
public function foo(int $bar)
{
...
}
}
, перегружающий метод foo и сужающий его ОДЗ.
В этой ситуации мы инстанс класса Child уже не можем передать в функцию baz поскольку метод в дочернем классе сужает ОДЗ, а значит мы не можем передать в метод foo аргумент строкового типа. Таким образом мы имеем нарушение LSP.
То, о чём говорит вышеозначенный RFC, так это о том, чтобы в дочерних классах можно было расширять типы аргументов переопределяемых методов. Если тип расширяется, то тогда контракт базового класса не нарушается: поскольку дочерние классы по-прежнему должны принимать на вход аргументы тех типов, которые задекларированы в родительском классе или интерфейсе.
Таким образом, LSP говорит о том, что субтипы не должны сужать супертип. В том числе, переопределение метода в субтипе может расширять ОДЗ метода, но не должно сужать его.
Извините, если ответ получился запутанным или сумбурным.
Статья 2012-го года. С тех прошло больше 4-х лет. С тех появились вышли версии 5.4, 5.5, 5.6, 7.0, 7.1
PHP шагнул далеко вперёд.
Нет, ну некоторые момент остаются актуальными: неконсистентная стандартная библиотека функций, неконсистентная последовательность аргументов (haystack-needle). Но вещи, которые там описаны постепенно становятся неактуальными. Посмотрите сколько было задепрекейчено к релизам 7.0, 7.1, 7.2
И это всё постепенно отпиливается.
Да, увы, тяжёлое наследие прошлого не даёт возможность сразу всё исправить и сделать красиво ибо тогда язык постигнет та же ситуация, которая сложилась вокруг раскола Python 2/3.
Но постепенно всё будет причёсано.
Зря вы так яростно апеллируете к этой уже очень старой статье.
З.Ы.
Очень надеюсь, что когда-нибудь этот RFC воплотят в жизнь (скорее всего, к версии 8.0): https://wiki.php.net/rfc/consistent_function_names
Вы не правы. Объекты жрут меньше, чем массивы: https://gist.github.com/nikic/5015323
Данный пост верен для PHP5. Для PHP7 легко проверить самостоятельно. Но, забегая вперёд, скажу, что объекты в PHP7 всё-равно занимают меньше памяти, чем массивы.
У нас используется error handler. Поэтому оператор подавления ошибок не используем.
Добавьте error handler и тогда время, затраченное на "@" улетит в космос.
Я замеряю время, которое тратится на отработку функции целиком, а не только её вызова.
Суть в том, что при наличии скалярного тайпхинта, значение аргумент будет преобразовано в требуемый строгим образом и далее это может привести к ускорению кода внутри функции поскольку в этом случае исчезает type juggling.
Скалярный тайпхинт таки отличается от приведения типа тем, что при тайпхинте значение аргумента не будет насильно приводится к требуемому.
Например, при вышеописанном объявлении функции корректными будут вызовы:
foo(123),foo("123"),foo("12.3e1")(последние 2 допустимы, если не указанdeclare(strict_types=1)), но некорректными (при которых будет выброшено исключение):foo(null),foo("123abc")(внезапно!),foo("abc"),foo([]),foo(new stdClass),…В то же время если заменить скалярный тайпхинт на приведение типа перед циклом, то тогда все перечисленные выше варианты станут а) допустимыми, б) приведение типа отработает во всех случаях.
Вы либо невнимательно читали, либо неправильно поняли. Скалярный тайпхинт может приводить к ускорению кода так как при использовании оного уменьшается количество неявных приведений типов.
Я хотел показать каким образом скалярный тайпхинт может привести к ускорению. В конце ответа я написал: «код может ускорится при использовании скалярных тайпхинтов, но в среднем общая производительность останется такой же».
Разумеется синтетика имеет мало общего с реальным приложением в продакшене.
Представим, что есть базовый класс:
Согласно «контракту» метод
fooдолжен принимать на вход аргумент строкового или целочисленного типа.И есть использование:
Тут мы говорим о том, что на вход должен поступить объект, являющийся инстансом класса
Parent, и в методfooэтого объект мы передаём аргумент. Так как контракт методаfooговорит о том, что на вход должен поступить либо строковой либо целочисленный аргумент, то и переменная$argтоже должна быть либо строкового, либо целочисленного типа.Тут всё логично.
Теперь представим, что есть класс , перегружающий метод
fooи сужающий его ОДЗ.В этой ситуации мы инстанс класса
Childуже не можем передать в функциюbazпоскольку метод в дочернем классе сужает ОДЗ, а значит мы не можем передать в методfooаргумент строкового типа. Таким образом мы имеем нарушение LSP.То, о чём говорит вышеозначенный RFC, так это о том, чтобы в дочерних классах можно было расширять типы аргументов переопределяемых методов. Если тип расширяется, то тогда контракт базового класса не нарушается: поскольку дочерние классы по-прежнему должны принимать на вход аргументы тех типов, которые задекларированы в родительском классе или интерфейсе.
Таким образом, LSP говорит о том, что субтипы не должны сужать супертип. В том числе, переопределение метода в субтипе может расширять ОДЗ метода, но не должно сужать его.
Извините, если ответ получился запутанным или сумбурным.
Полагаю статус коды 6XY должны быть зарезервированы для менеджеров. Первый из них — "600 — We Need This Feature Yesterday".
Классика — Gang of Four
В 2015-м году было обсуждение в php internals. Длинное, тяжёлое.
https://www.mail-archive.com/internals@lists.php.net/msg80837.html
PHP шагнул далеко вперёд.
Нет, ну некоторые момент остаются актуальными: неконсистентная стандартная библиотека функций, неконсистентная последовательность аргументов (haystack-needle). Но вещи, которые там описаны постепенно становятся неактуальными. Посмотрите сколько было задепрекейчено к релизам 7.0, 7.1, 7.2
И это всё постепенно отпиливается.
Да, увы, тяжёлое наследие прошлого не даёт возможность сразу всё исправить и сделать красиво ибо тогда язык постигнет та же ситуация, которая сложилась вокруг раскола Python 2/3.
Но постепенно всё будет причёсано.
Зря вы так яростно апеллируете к этой уже очень старой статье.
З.Ы.
Очень надеюсь, что когда-нибудь этот RFC воплотят в жизнь (скорее всего, к версии 8.0): https://wiki.php.net/rfc/consistent_function_names
Мне кажется, что это самый развитый проект http-сервера на PHP
Данный пост верен для PHP5. Для PHP7 легко проверить самостоятельно. Но, забегая вперёд, скажу, что объекты в PHP7 всё-равно занимают меньше памяти, чем массивы.
Добавьте error handler и тогда время, затраченное на "@" улетит в космос.