Про́стір назв, також про́стір іме́н або іменни́й про́стір () — концепція у програмуванні, призначена для розмежування різних множин ідентифікаторів і уникнення конфліктів між їхніми назвами.
Ідентифікатор, зосереджений у просторі імен, асоціюється з цим простором. Один і той самий ідентифікатор може бути незалежно визначений у декількох просторах. Значення, пов'язане з ідентифікатором, який знаходиться в одному просторі імен, може мати (чи не мати) таке ж саме значення, як і той самий ідентифікатор, визначений у іншому просторі. Мови з підтримкою просторів імен визначають правила, завдяки яким, можна визначити до якого простору імен належить ідентифікатор (тобто його значення).
Приклад: Андрій працює в компанії X, а ID. Він має ідентифікатор працівника, який дорівнює 123. Олег працює в компанії Y, а його ID так само дорівнює 123. Значення в обох єдине (з точки зору якоїсь системи обліку), завдяки чому Андрія та Олега можна розрізнити при співпадаючих ID, це характеризує їх приналежність до різних підприємств. Різниця компаній, у цьому випадку, являє собою систему різних просторів імен (одна компанія - один простір). Наявність двох працівників у компанії з однаковими ID створює значні проблеми при їх використанні, наприклад, по платіжному чеку, в якому буде вказано працівник з ID 123, буде досить важко визначити працівника, якому цей чек призначається.
У великих базах даних можуть існувати сотні та тисячі ідентифікаторів. Простори назв (або схожі структури) реалізують механізм для приховування локальних ідентифікаторів. Угрупування логічно пов'язаних ідентифікаторів, у відповідних просторах імен, створює модульну систему. Обмеження видимості змінних може також проводитися шляхом завдання класу її пам'яті .
Операційні системи, а також більшість серед сучасних мов програмування, забезпечують підтримку власної моделі просторів імен: використовують каталоги, (або папки) як модель простору імен. Це дозволяє існувати двом файлам з однаковим ім'ям (за умови, що вони знаходяться в різних каталогах). У деяких мовах програмування (наприклад, C ++, Python) ідентифікатори імен просторів самі асоціюються з необхідними просторами. У таких мовах простір імен може вкладатися один до одного, формуючи дерево просторів імен. Корінь такого дерева отримує назву глобального простору імен.
Використання у мовах
Java Java-пакети втілюють ідею просторів імен. Увесь код, зосереджений усередині пакету, який не потребує явно заданого ім'я. Код з інших пакетів доступний при префіксному посиланню на ім'я пакету перед відповідним ідентифікатором, наприклад, клас String в пакеті java.lang може бути викликаний як java.lang. String (даний спосіб відомий як повне ім'я класу ). Як і в C ++, Java пропонує конструкцію, що робить необов'язковим вказівку ім'я пакета ( import ). У той самий час, деякі особливості (як, наприклад, відображення ) вимагають від програміста використання повного імені.
На відміну від C ++, простір імен у Java не є ієрархічно впорядкованим через синтаксис мови. Проте, пакети іменуються в ієрархічному стилі. Наприклад, усі пакети, які починаються з java , є частиною платформи Java - пакет java.lang, що містить базові класи мови, у той самий час у java.lang.reflect [Архівовано 31 січня 2019 у Wayback Machine.] містяться базові класи, специфічні для відображення (рефлексії).
У мові Java (так само, як і в Ада , C # та інших мовах) простори імен / пакети відображають семантичні категорії коду. Як приклад, у C # namespace System містить код, що реалізується системою (платформа . NET). Як саме визначаються ці категорії і наскільки глибока ієрархія - залежить від самої мови.
Область видимості Функція і клас можуть бути визначені, як неявний простір імен, складно пов'язані з видимістю, доступністю і періодом життя об'єкта .
C# У мові C # існують простори імен, які вживаються аналогічно C ++.
Python В Python кожен ідентифікатор може знаходитись в локальному або глобальному просторі назв, або всередині певного об'єкта (модуля, або будь-якого іншого). Функція locals() повертає словник (асоціативний масив) з ідентифікаторами локального простору назв, globals() — глобального. Функція dir() покаже список ідентифікаторів доступних з поточного фрейму, якщо викликана без параметрів, і список ідентифікаторів всередині об'єкта, якщо викликана з якимось об'єктом.
Змінна оголошена всередині іншої функції потрапляє в локальний простір назв, якщо перед цим не задекларувати її глобальною використавши ключове слово global.
У Python ідея просторів імен реалізована у модулях. (Так само, як і у пакетах Java)
C++ всі ідентифікатори знаходяться в глобальному просторі назв, тому часті випадки існування двох різних об'єктів з однаковими назвами, що призводить до помилок. Щоб цьому запобігти глобальний простір назв ділять на менші. Наприклад стандартну бібліотеку C++ винесено в область названу std.
Простір імен визначається блоком інструкцій, а саме: namespace foo { int bar; } Усередині цього блоку ідентифікатори можуть викликатися у той спосіб, яким вони були оголошені. Важливо, що поза блоком потрібна вказівка назви простору імен перед ідентифікатором. Наприклад, поза namespace foo ідентифікатор bar має вказуватися, як foo::bar . У мові C ++ містяться деякі інші конструкції, які роблять подібні вимоги необов'язковими. Так, при додаванні рядка: using namespace foo; Більше не потрібно вказується префікс foo::у код, . Ще один приклад: namespace Namespace12 { int foo=0; }
void func1() { using namespace Namespace12; // тепер всі імена з простору імен Namespace12 буде видно тут без додаткових префіксів
++foo; }
void func2() { // а тут ім'я потрібно уточнити: Namespace12::foo = 42; } Код, який не оголошено явно у просторі імен, за замовчуванням, вважається оголошеним у глобальному просторі імен.
Дозвіл просторів імен в C ++ прописується ієрархічно. Це означає, що у гіпотетичному просторі назв їжа::бульйон, ідентифікатор курка буде позначати їжа::бульйон::курка (якщо простір існує). У випадку, якщо не існує, то тоді він перепосилається на їжа::курка (такий простір існує). Якщо ж і цей простір не існуючий-то: курка посилається на ідентифікатор у глобальному просторі.
Зазвичай, простір імен у C ++ використовується для уникнення випадків колізій імен namespace { int a; void f() { /*...*/ } int g() { /*...*/ } } Неможливо здійснити доступ з однієї одиниці трансляції до частини анонімного простору імен до іншої одиниці.
Хоча простір імен активно використовуються у сучасному коді, значна частина старого коду не має подібних можливостей. Наприклад, уся стандартна бібліотека мови C ++ визначена всередині namespace std , але до стандартизації багато компонентів спочатку були визначені у глобальному просторі.
Також можна зробити відкритим до перегляду не весь простір, а окремі імена всередині нього, наприклад: namespace foo { int bar; int somelse; } int main () { using foo::bar; //Робить видимим тільки bar, somelse невидимий! return 0; }
Створення просторів назв Щоб створити простір назв використовують ключове слово namespace. Код: namespace <назва_простору> { // Оголошення } Доступ до ідентифікаторів з просторів назв Щоб отримати доступ до об'єктів з простору назв з за його меж використовують оператор дозволу області видимості ( :: ). Наприклад: namespace some { int something; } something=1; // Помилка, something невидиме. some::something=1; // Ми вказали в якій області його шукати.
Правда такий спосіб може бути незручним, якщо ми використовуємо багато ідентифікаторів не з нашої області видимості. Щоб полегшити нам життя придумана директива using. Хай ми маємо простір кімнати: namespace room { Wall wall1, wall2, wall3, wall4; Ceil ceil; } Можна внести стелю в наш простір назв, написавши, що ми її будемо використовувати: using room::ceil; ceil = 42; // Тепер стеля видима wall1 = wall2; // А таке все ще викличе помилку! А можна взагалі розкрити увесь простір назв: using room; wall1 = wall2 = wall3; // Всі ідентифікатори з кімнати доступні
JavaScript Мова надає можливість для реалізації просторів імен, незважаючи на відсутність формальної підтримки, використовуючи об'єктну концепцію мови: var NameSpace_1 = {}; var NameSpace_2 = new Object(); //Створюються два простори імен
NameSpace_1.a = 100; NameSpace_2.a = "Суниця"; //Змінні a - у кожного свої
with(NameSpace_1) //Вказуємо простір імен за замовчуванням { a += 10; NameSpace_2.a += a; //Змінна a простору імен NameSpace_2 дорівнюватиме "Суниця110" }
XML У XML специфікація просторів XML імен визначає унікальність імен елементів і атрибутів у документі, аналогічно ролям просторів імен у мовах програмування. За допомогою просторів імен XML-документи можуть містити імена елементів або атрибутів з більш ніж одного словника XML. <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"> <foaf:Person rdf:about="#JW"> … xmlns (XML Namespace) - простір імен XML. Підключаються RDF (для створення документа RDF ), FOAF і RDF Schema ( формат оформлення RDF ).
FOAF — це теж простір RDF документа, тому перевіряється його оформлення згідно зі словником (правилами, специфікації) RDF.
PHP Починаючи з версії 5.3.0 у PHP введено поняття простору імен. <?php namespace my\name; // визначимо новий простір імен
class MyClass {} function myfunction() {} const MYCONST = 1;
$a = new MyClass; // виклик всередині простору my\name $c = new \my\name\MyClass; // використовуємо повне ім'я, яке включає назву простору імен $d = new \globalClass; // звернення до класу з глобального простору імен ?>Важливо те, що директива namespace повинна бути першим рядком коду у файлі. Виняток є ключове слово declare, яке може передувати директиві namespace. Не допускається, навіть, виведення HTML перед першою конструкцією «<?php».
Опис синтаксису є на офіційному сайті проекту PHP.
Common Lisp У стандартному синтаксисі Common Lisp є табличні простори імен, які реалізуються через систему пакетів. Необхідно вказати назву ідентифікатора (символу) для використання, а саме: повну назву (назва пакету, двокрапка та назва самого символу).
У Allegro Common Lisp реалізовано нестандартне розширення Common Lisp - ієрархічний простір імен, де пакети розділяються використанням крапки, у стилі Java , а ідентифікатор від пакетів відокремлюється двокрапкою. Також, можливі звернення до суміжних вузлів в ієрархії просторів імен через посилання до відносних шляхів, використовуючи двокрапку. Простори імен у Common Lisp є динамічними - вони створюються, наповнюються і знищуються під час виконання програми, хоча здебільшого застосовується декларативна форма їх опису за допомогою форми defpackage .
PureBasic У PureBasic 5.20 , була введена підтримка простору імен, реалізована у вигляді модулів. Простір імен визначається блоком команд Module і EndModule і не залежить від розташування у первинних файлах. Це означає, що в одному файлі, можуть існувати декілька модулів, чи навпаки - код модуля може бути розділений на декілька файлів. За замовчуванням, увесь простір модуля приховано, для того щоб зробити видимим окремі його елементи, їх необхідно оголосити у спеціальному блоці команд DeclareModule / EndDeclareModule. Усе, що не оголошено у цьому блоці, не можливо переглянути поза межами модуля, і спроба доступу приведе до повідомлення компілятора про порушення прав доступу. DeclareModule Count x=0 ; Public elements Declare Counter() EndDeclareModule
Module Count
y=0 ; Private elements
Procedure Counter() y+1 ProcedureReturn y EndProcedure
EndModule
Count::x = 10 ; Запис числа у змінну (для прикладу). Debug Count::Counter() ; Виклик процедури, що використовує ім'я модуля.
UseModule Count ; Відображення модуля у дійсний простір. Debug Counter() ; Відкритий доступ (Public) до елементів без вказівок на ім'я модуля.