Что такое namespace ы и зачем они нужны

Что такое namespace ы и зачем они нужны

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

Ниже приведён пример трёх вариантов синтаксиса в реальном коде:

namespace Foo \ Bar \ subnamespace ;

const FOO = 1 ;
function foo () <>
class foo
<
static function staticmethod () <>
>
?>

namespace Foo \ Bar ;
include ‘file1.php’ ;

const FOO = 2 ;
function foo () <>
class foo
<
static function staticmethod () <>
>

/* Неполные имена */
foo (); // определяется как функция Foo\Bar\foo
foo :: staticmethod (); // определяется как класс Foo\Bar\foo с методом staticmethod
echo FOO ; // определяется как константа Foo\Bar\FOO

/* Полные имена */
subnamespace \ foo (); // определяется как функция Foo\Bar\subnamespace\foo
subnamespace \ foo :: staticmethod (); // определяется как класс Foo\Bar\subnamespace\foo
// c методом staticmethod
echo subnamespace \ FOO ; // определяется как константа Foo\Bar\subnamespace\FOO

/* Абсолютные имена */
\ Foo \ Bar \ foo (); // определяется как функция Foo\Bar\foo
\ Foo \ Bar \ foo :: staticmethod (); // определяется как класс Foo\Bar\foo с методом staticmethod
echo \ Foo \ Bar \ FOO ; // определяется как константа Foo\Bar\FOO
?>

Пример #1 Доступ к глобальным классам, функциям и константам из пространства имён

function strlen () <>
const INI_ALL = 3 ;
class Exception <>

$a = \ strlen ( ‘hi’ ); // вызывает глобальную функцию strlen
$b = \ INI_ALL ; // получает доступ к глобальной константе INI_ALL
$c = new \ Exception ( ‘error’ ); // Создаёт экземпляр глобального класса Exception
?>

Источник

Пространства имен в PHP, разъяснение

Прим.пер.: Я в курсе, что на момент перевода актуальная версия PHP — 5.5, а также что есть мудрая книга мануал. Но мне показалось интересным, то как автор преподносит namespace функционал, возможно кому-то из тех, кто только постигает азы (да и не только, есть немало бородатых разработчиков, остановившихся на PHP 5.2), статья поможет проникнуться. Ходор.

Глобальное пространство имен

Вот такой, очень простой класс:

Ничего особенно, как видите, и если вы хотите использовать его, просто сделайте так:

Хорошо, хорошо, извини. Суть в том, что мы можем думать об этом классе, как находящимся в глобальном пространстве имён.Я не совсем уверен, что это правильный термин, но на мой взгляд это звучит вполне уместно. Собственно, это значит то, что класс не принадлежит никакому пакету, просто обычный класс.

Простое использование пространств имён

Давайте создадим еще одного Эддарда, рядом с тем, глобальным.
Что такое namespace ы и зачем они нужны. Смотреть фото Что такое namespace ы и зачем они нужны. Смотреть картинку Что такое namespace ы и зачем они нужны. Картинка про Что такое namespace ы и зачем они нужны. Фото Что такое namespace ы и зачем они нужны
Здесь у нас очень похожий класс с одним небольшим изменением, добавлена директива пространства имен. Строка namespace Stark; говорит PHP что мы работаем в пространстве имен Stark и любой код (объявление классов, функций, переменных и т.д.) будет относиться к нему.

Итак, нам нужно создать нового Эдда, если вы решили что это нужно сделать вот так:

То нет, это не так. Здесь мы получаем экземпляр класса из первого примера, который мы создали ранее. Не тот, в пространстве имен Stark. Давайте попробуем создать экземпляр Эддарда Старка.

Для создания экземпляра класса нам нужно предварить имя класса префиксом из названия пространства имен, которому класс принадлежит, а в качестве разделителя использовать обратную косую черту. В итоге у нас есть экземпляр именно того класса, что нам нужен. Разве это не волшебно?

К слову сказать, пространства имён могут образовывать сколь угодно сложную иерархию, используя столько уровней, сколько потребуется. Например:

Теория относительности

Помните, как я сказал вам, что PHP всегда работает относительно текущего пространства имен. Давайте взглянем на это в действии:

Добавив директиву пространства имён, мы дали понять PHP, что мы находимся в пространстве имён Stark. Так как именно в нем мы определили класс Eddard, то именно его мы и получим. Видите — все относительно.

Сейчас, когда мы изменили пространство имён, у нас возникла одна маленькая проблема. Есть идеи, о чем я? А как нам теперь получить наш оригинальный класс Eddard? Ну тот, который в глобальном пространстве?

К счастью в PHP есть трюк, который позволит нам решить эту проблему — просто добавив \ к имени класса.

Видя ведущий слеш PHP понимает, что нужно выглянуть за пределы текущего namespace и создает экземпляр нужного нам класса.

А сейчас включи свое воображение. Представь, что у нас есть класс из другого пространства имен, названный Tully\Edmure. Сейчас нам нужно использовать его внутри пространства Stark. И как нам это сделать?
Что такое namespace ы и зачем они нужны. Смотреть фото Что такое namespace ы и зачем они нужны. Смотреть картинку Что такое namespace ы и зачем они нужны. Картинка про Что такое namespace ы и зачем они нужны. Фото Что такое namespace ы и зачем они нужны

И снова нам пришлось использовать обратный слеш, чтобы перейти к глобальной видимости, прежде чем создать экземпляр класса в пространстве Tully.

Вообще, ссылаться вот так на классы из других пространств имен, используя полную иерархию в названии, может быть довольно утомительно. Но к счастью, есть возможность сделать ярлык, давайте посмотрим:

А, еще один маленький трюк! Мы можем дать нашим импортируемым классам прозвища:

Давая Daenerys из пространства Dothraki прозвище Khaleesi, мы можем использовать оба класса Daenerys. Довольно удобно, там мы можем использовать все необходимые классы в нашем приложении.
Что такое namespace ы и зачем они нужны. Смотреть фото Что такое namespace ы и зачем они нужны. Смотреть картинку Что такое namespace ы и зачем они нужны. Картинка про Что такое namespace ы и зачем они нужны. Фото Что такое namespace ы и зачем они нужны

Структура

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

Скажем, я хочу создать библиотеку с открытым исходным кодом. Мне бы очень хотелось, чтобы другие могли использовать мой код, это было бы здорово! Беда в том, что имена классов в моем коде конфликтовали с собственным приложением пользователя моей библиотеки. Это было бы ужасно неудобно. Вот как я решу эту проблему:

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

Начав использовать composer, вы узнаете, как использовать пространства имён для упрощения автозагрузки кода. Я настоятельно рекомендую вам взглянуть на этот полезный механизм.

Недостатки

По правде говоря, я чувствую себя немного виноватым за то, что назвал этот подзаголовок «Недостатки». То, о чем я собираюсь говорить, на самом деле ошибкой не является.

Дело в том, что в других языках функционал пространств имён реализован похожим образом, и при этом языки обеспечивают дополнительный функционал для взаимодействия с пространствами имён.

В Java, например, вы можете импортировать несколько классов в текущее пространство имен, используя оператор импорта. В Java, import является аналогом use и он использует точки, чтобы отделить вложенные пространства имен (или пакеты). Вот пример:

В PHP у вас так не выйдет. Вы должны импортировать каждый класс в отдельности. Извините. Собственно, почему я извиняюсь? Идите и жалуйтесь команде разработчиков PHP, но я прошу вас — будьте вежливы. Они сделали много интересного в последнее время.

Вот изящный трюк, чтобы немного сгладить озвученную проблему. Представьте себе, что у нас есть структура классов из предыдущего примера. Мы можем взять часть подпространства и дать ему псевдоним.
Что такое namespace ы и зачем они нужны. Смотреть фото Что такое namespace ы и зачем они нужны. Смотреть картинку Что такое namespace ы и зачем они нужны. Картинка про Что такое namespace ы и зачем они нужны. Фото Что такое namespace ы и зачем они нужны
Это может быть полезным при использовании большого числа классов. Добра всем!

Все пожелания и предложения с радостью приму в личку, спасибо.

Источник

Пространства имен в PHP

На хабре можно найти немало статей о пространствах имен в PHP, но мне помогла именно эта, и именно ей я хочу поделится. Наверняка найдутся те, кому этот перевод поможет.

Путь к поддержке пространств имен в PHP был тернистым. Но к счастью она была добавлена к языку в версии PHP 5.3, и структура PHP кода значительно улучшилась с тех пор. Но как именно нам их использовать?

Что такое пространства имен?

«Не забывайте обратный слеш, когда Вы храните имя пространства имен в виде строки!»

Представьте себе пространство имен, как ящик, в который Вы можете положить все что угодно: карандаш, линейку, кусок бумаги и так далее. Это Ваши вещи. Прямо под вашим ящиком, располагается еще чей-то ящик, и его хозяин хранит те же вещи в нем. Чтобы избежать использования предметов друг друга, Вы решили маркировать ящики так чтобы стало ясно, что кому принадлежит.

Ранее разработчикам приходилось использовать префиксы с нижним подчеркиванием в своих классах, функциях и константах для разделения кода. Это эквивалентно тому, что каждый будет маркировать свои вещи и храниться они будут в одном большом ящике. Конечно, это по крайней мере хоть какая-то организации, но это очень неэффективно.

Пространства имен, помогут! Вы можете объявить одни и те же функцию, класс, интерфейс и определить константу в отдельных пространствах имен, не получая фатальных ошибок. По своей сути, пространство имен не более чем иерархически маркированные блоки кода содержащие обычный PHP код.

Вы используете их!

Важно понимать, что Вы косвенно используете пространства имен; Начиная с PHP 5.3, все определения, которые еще не объявлены в определенных пользователем пространствах имен, подпадают под глобальное пространство имен.

Обратите внимание что использование пространства имен не является обязательным.
Ваш PHP скрипт будет прекрасно работать без них, и такое поведение не очень скоро изменится.

Определение пространства имен

Вы можете использовать несколько пространств имен в одном файле.

Вы также можете использовать одно и тоже пространство имен для нескольких разных файлов; процесс подключения файлов автоматически объединит их. Это хорошая практика кодирования, ограничить количество определений пространства имен до одного файла, так же, как Вы могли бы сделать это с классами.

Пространство имен используется, чтобы избежать противоречивых определений и ввести больше гибкости и организации в программный код.

Обратите внимание, что фигурные скобки, совершенно необязательны. На самом деле, используя правило одного пространства имен в одном файле и опуская фигурные скобки Вы делаете ваш код намного чище — нет никакой необходимости, делать отступ(табуляцию) для вложенного кода.

Подпространства имен

Для обеспечения гибкости, разумно хранить вложенные пространства имен в подкаталогах. Это способствует структурированию проекта и позволяет гораздо проще использовать его автозагрузчикам, которые следуют стандарту PSR-4.

PHP использует обратный слэш, в качестве разделителя пространства имен.

Что такое namespace ы и зачем они нужны. Смотреть фото Что такое namespace ы и зачем они нужны. Смотреть картинку Что такое namespace ы и зачем они нужны. Картинка про Что такое namespace ы и зачем они нужны. Фото Что такое namespace ы и зачем они нужны

Интересный факт: в RFC, чтобы решить, какой разделитель пространства имен следует использовать, рассматривался вариант использования смайлика.

Вы можете использовать столько вложенных пространств имен, сколько хотите.

Определение подпространства имен с вложенными блоками кода не поддерживается. Следующий пример будет возвращать фатальную ошибку: «Объявления пространств имен не могут быть вложенными (Namespace declarations cannot be nested)».

Вызов кода из пространства имен

Если Вы хотите, создать новый экземпляр объекта, вызвать функцию или использовать константы из разных пространств имен, Вы используете обратный слэш. Существует три типа определений имени пространства имен:

Неполное имя

Это имя класса, функции или константы, не включающее в себя ссылку к какому бы то ни было пространству имён. Для тех, кто только начинает работать с пространством имен, это привычная точка зрения.

Полное имя

Так мы получаем доступ к иерархии подпространства имен; разделяется обратным слэшем.

Пример ниже возвратит фатальную ошибку: «Fatal error: Class ‘MyProject\Database\MyProject\FileAccess\Input’ not found», потому что MyProject\FileAccess\Input не имеет отношения к пространству имен в котором Вы находитесь.

Абсолютное имя

Полные и неполные имена используются по отношению к пространству имен в котором Вы находитесь в настоящее время. Они могут быть использованы только для определения доступа на этом уровне или нырять глубже в иерархию пространства имен.

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

Нам не обязательно использовать полное имя для внутренних функций PHP. Неполные имена для функций и констант будут определяться в глобальном пространстве имен, если они не определены в текущем пространстве имен.

Зная это, мы можем теперь перегружать внутренние функции PHP, при этом имея возможность вызвать первоначальную функцию (или константу).

Динамические вызовы

PHP — динамический язык программирования; так что Вы можете применять этот функционал для вызова кода из пространства имён. Это, по существу тоже, что использование динамического имени класса или подключение динамического файла используя переменную для хранения его имени. Разделитель имен PHP использует те же метасимволы в строках. Не забывайте про обратный слеш, когда Вы храните имя пространства имен в виде строки!

Ключевое слово namespace

Ключевое слово namespace используется не только для определения пространства имен, оно также может быть использован для вызова в текущем пространстве имен, функционально аналогичный ключевому слову self для классов.

Константа __NAMESPACE__

Так же как ключевое слово self не может быть использовано для определения имени текущего класса, также и ключевое слово namespace не может использоваться для текущего пространства имен. Поэтому мы используем константу __NAMESPACE__

Эта константа является весьма полезной в начале изучения пространства имен; также она очень полезна при отладке. Так как это строка, она может быть использована в сочетании с динамическими вызовами кода, рассмотренные выше.

Импорт или создание псевдонима имени

не обязательно использовать в пространствах имен

Важная особенность пространств имен в PHP — это возможность ссылаться на внешнее абсолютное имя по псевдониму, или импортирование.

Как это использовать

Абсолютное имя может быть привязаны к более короткому неполному имени, так что вам не придется писать его абсолютное имя каждый раз, когда Вы хотите его использовать. Создание псевдонима или импорт должны происходить в родительском пространстве имен или в глобальном. Попытка сделать это в рамках метода или функции является недопустимым синтаксисом (invalid syntax).

Альтернативой, является возможность присвоения псевдонима с другим именем

Вы также можете импортировать такие глобальные классы, как Exception. При импорте, вам не придется писать его абсолютное имя.

Обратите внимание, что для имен в пространстве имен нет необходимости в начальном обратном слеше и его присутствие там не рекомендуется, так как импортируемые имена должны быть абсолютными и не обрабатываются относительно текущего пространства имен.

Хотя есть поддержка динамического вызова пространства имен, динамический импорт не поддерживается.

Источник

Урок №53. Пространства имен

Этот урок является продолжением урока №24.

Конфликт имен

Конфликт имен возникает, когда два одинаковых идентификатора находятся в одной области видимости, и компилятор не может понять, какой из этих двух следует использовать в конкретной ситуации. Компилятор или линкер выдаст ошибку, так как у них недостаточно информации, чтобы решить эту неоднозначность. Как только программы увеличиваются в объемах, количество идентификаторов также увеличивается, следовательно, увеличивается и вероятность возникновения конфликтов имен.

Рассмотрим пример такого конфликта. boo.h и doo.h — это заголовочные файлы с функциями, которые выполняют разные вещи, но имеют одинаковые имена и параметры.

Если boo.h и doo.h скомпилировать отдельно, то всё пройдет без инцидентов. Однако, соединив их в одной программе, мы подключим две разные функции, но с одинаковыми именами и параметрами, в одну область видимости (глобальную), а это, в свою очередь, приведет к конфликту имен. В результате, компилятор выдаст ошибку. Для решения подобных проблем и добавили в язык С++ такую концепцию, как пространства имен.

Что такое пространство имен?

Пространство имен определяет область кода, в которой гарантируется уникальность всех идентификаторов. По умолчанию, глобальные переменные и обычные функции определены в глобальном пространстве имен. Например:

Глобальная переменная g_z и функция boo() определены в глобальном пространстве имен.

В примере, приведенном выше, при подключении файлов boo.h и doo.h обе версии doOperation() были включены в глобальное пространство имен, из-за чего, собственно, и произошел конфликт имен.

Чтобы избежать подобных ситуаций, когда два независимых объекта имеют идентификаторы, которые могут конфликтовать друг с другом при совместном использовании, язык C++ позволяет объявлять собственные пространства имен через ключевое слово namespace. Всё, что объявлено внутри пользовательского пространства имен, — принадлежит только этому пространству имен (а не глобальному).

Перепишем заголовочные файлы из вышеприведенного примера, но уже с использованием namespace:

Результатом будет еще одна ошибка:

C:\VCProjects\Test.cpp(15) : error C2065: ‘doOperation’ : undeclared identifier

Случилось так, что когда мы попытались вызвать функцию doOperation(), компилятор заглянул в глобальное пространство имен в поисках определения doOperation(). Однако, поскольку ни одна из наших версий doOperation() не находится в глобальном пространстве имен, компилятор не смог найти определение doOperation() вообще!

Существует два разных способа сообщить компилятору, какую версию doOperation() следует использовать: через оператор разрешения области видимости или с помощью using-стейтментов (о них мы поговорим на следующем уроке).

Доступ к пространству имен через оператор разрешения области видимости (::)

Первый способ указать компилятору искать идентификатор в определенном пространстве имен — это использовать название необходимого пространства имен вместе с оператором разрешения области видимости ( :: ) и требуемым идентификатором.

Например, сообщим компилятору использовать версию doOperation() из пространства имен Boo :

Источник

Пространства имен (C++)

В следующем примере показано объявление пространства имен и продемонстрированы три способа доступа к членам пространства имен из кода за его пределами.

Использование полного имени:

Чтобы добавить в область видимости один идентификатор, используйте объявление using:

Чтобы добавить в область видимости все идентификаторы пространства имен, используйте директиву using:

Директивы using

using Директива позволяет использовать все имена в namespace для использования без using в качестве явного квалификатора. Использование директивы using в файле реализации (т. е. *. cpp) при использовании нескольких различных идентификаторов в пространстве имен; Если вы используете только один или два идентификатора, рассмотрите использование объявления using, чтобы привести эти идентификаторы в область, а не все идентификаторы в пространстве имен. Если локальная переменная имеет такое же имя, как и переменная пространства имен, то переменная пространства имен будет скрытой. Создавать переменную пространства имен с те же именем, что и у глобальной переменной, является ошибкой.

Директиву using можно поместить в верхнюю часть CPP-файла (в области видимости файла) или внутрь определения класса или функции.

Без особой необходимости не размещайте директивы using в файлах заголовков (*.h), так как любой файл, содержащий этот заголовок, добавит все идентификаторы пространства имен в область видимости, что может вызвать скрытие или конфликты имен, которые очень трудно отлаживать. В файлах заголовков всегда используйте полные имена. Если эти имена получаются слишком длинными, используйте псевдоним пространства имен для их сокращения. (См. ниже.)

Объявление пространств имен и их членов

Как правило, пространство имен объявляется в файле заголовка. Если реализации функций находятся в отдельном файле, определяйте имена функций полностью, как показано в следующем примере.

Реализации функций в контосодата. cpp должны использовать полное имя, даже если поместить using директиву в начало файла:

Пространство имен может быть объявлено в нескольких блоках в одном файле и в нескольких файлах. Компилятор соединит вместе все части во время предварительной обработки и полученное в результате пространство имен будет содержать все члены, объявленные во всех частях. Примером этого является пространство имен std, которое объявляется в каждом из файлов заголовка в стандартной библиотеке.

Члены именованного пространства имен могут определяться за его границами, если они объявлены путем явной квалификации определяемого пространства имен. Однако определение должно располагаться после точки объявления в пространстве имен, окружающем то пространство имен, где находится объявление. Пример:

Эта ошибка может возникнуть, когда члены пространства имен объявляются в нескольких файлах заголовка и эти заголовки не включены в правильном порядке.

Глобальное пространство имен

Пространство имен std

Вложенные пространства имен

Пространства имен могут быть вложенными. Обычное вложенное пространство имен имеет неполный доступ к членам родительского элемента, но родительские элементы не имеют неполного доступа к вложенному пространству имен (если только оно не объявлено как встроенное), как показано в следующем примере:

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

Встроенные пространства имен (C++ 11)

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

В следующем примере показано, как можно объявить специализацию в родительском пространстве имен шаблона, объявленного во встроенном пространстве имен.

Встроенные пространства имен можно использовать как механизм управления версиями для управления изменениями в открытом интерфейсе библиотеки. Например, можно создать одно родительское пространство имен и инкапсулировать каждую версию интерфейса в своем собственном пространстве имен, вложенном в родительское. Пространство имен, которое содержит самую последнюю или основную версию, квалифицируется как встроенное и поэтому представляется так, будто оно является непосредственным членом родительского пространства имен. Клиентский код, вызывающий Parent::Class, автоматически привязывается к новому коду. Клиенты, которые предпочитают использовать старую версию, могут по-прежнему получить доступ к ней, используя полный путь к вложенному пространству имен, содержащему данный код.

Ключевое слово inline должно применяться к первому объявлению пространства имен в единице компиляции.

Псевдонимы пространств имен

Имена пространств имен должны быть уникальными, из-за чего зачастую они получаются не слишком короткими. Если длина имени затрудняет чтение кода или утомительно вводить файл заголовка, где нельзя использовать директивы using, можно создать псевдоним пространства имен, который служит аббревиатурой для фактического имени. Пример:

анонимные или безымянные пространства имен

Вы можете создать явное пространство имен, но не присвоить ему имя.

Это называется безымянным или анонимным пространством имен, и его можно использовать, если нужно сделать объявления переменных невидимыми для кода в других файлах (т. е. обеспечить их внутреннюю компоновку) без создания именованного пространства имен. Весь код, находящийся в том же файле, может видеть идентификаторы в безымянном пространстве имен, но эти идентификаторы, а также само пространство имен, будет невидимым за пределами этого файла или, точнее, вне блока перевода.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *