Простір імен (програмування)
Простір імен (англ. namespace) - деяка множина, під якою мається на увазі модель, абстрактне сховище або оточення, створене для логічного угрупування унікальних ідентифікаторів (тобто імен ).
Ідентифікатор, зосереджений у просторі імен, асоціюється з цим простором . Один і той самий ідентифікатор може бути незалежно визначений у декількох просторах. Значення, пов'язане з ідентифікатором, який знаходиться в одному просторі імен, може мати (чи не мати) таке ж саме значення, як і той самий ідентифікатор, визначений у іншому просторі. Мови з підтримкою просторів імен визначають правила, завдяки яким, можна визначити до якого простору імен належить ідентифікатор (тобто його значення).
Приклад: Андрій працює в компанії X, а ID (скорочено від англ. Identifier - ідентифікатор). Він має ідентифікатор працівника, який дорівнює 123. Олег працює в компанії Y, а його ID так само дорівнює 123. Значення в обох єдине (з точки зору якоїсь системи обліку), завдяки чому Андрія та Олега можна розрізнити при співпадаючих ID, це характеризує їх приналежність до різних підприємств. Різниця компаній, у цьому випадку, являє собою систему різних просторів імен (одна компанія - один простір). Наявність двох працівників у компанії з однаковими ID створює значні проблеми при їх використанні, наприклад, по платіжному чеку, в якому буде вказано працівник з ID 123, буде досить важко визначити працівника, якому цей чек призначається.
У великих базах даних можуть існувати сотні та тисячі ідентифікаторів. Простори назв (або схожі структури) реалізують механізм для приховування локальних ідентифікаторів. Угрупування логічно пов'язаних ідентифікаторів, у відповідних просторах імен, створює модульну систему. Обмеження видимості змінних може також проводитися шляхом завдання класу її пам'яті .
Операційні системи, а також більшість серед сучасних мов програмування, забезпечують підтримку власної моделі просторів імен: використовують каталоги, (або папки) як модель простору імен. Це дозволяє існувати двом файлам з однаковим ім'ям (за умови, що вони знаходяться в різних каталогах). У деяких мовах програмування (наприклад, C ++, Python) ідентифікатори імен просторів самі асоціюються з необхідними просторами. У таких мовах простір імен може вкладатися один до одного, формуючи дерево просторів імен. Корінь такого дерева отримує назвуглобального простору імен .
Границі
Один із способів завдання границі - використання області видимості .
Використання у мовах
C++
Простір імен визначається блоком інструкцій, а саме:
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;
}
Java
Java-пакети втілюють ідею просторів імен. Увесь код, зосереджений усередині пакету, який не потребує явно заданого ім'я. Код з інших пакетів доступний при префіксному посиланню на ім'я пакету перед відповідним ідентифікатором, наприклад, клас String в пакеті java.lang може бути викликаний як java.lang.
String
(даний спосіб відомий як повне ім'я класу ). Як і в C ++, Java пропонує конструкцію, що робить необов'язковим вказівку ім'я пакета ( import
). У той самий час, деякі особливості (як, наприклад, відображення ) вимагають від програміста використання повного імені.
На відміну від C ++, простір імен у Java не є ієрархічно впорядкованим через синтаксис мови. Проте, пакети іменуються в ієрархічному стилі. Наприклад, усі пакети, які починаються з java
, є частиною платформи Java - пакет java.lang,
що містить базові класи мови, у той самий час у java.lang.reflect містяться базові класи, специфічні для відображення (рефлексії).
У мові Java (так само, як і в Ада , C # та інших мовах) простори імен / пакети відображають семантичні категорії коду. Як приклад, у C # namespace System
містить код, що реалізується системою (платформа . NET). Як саме визначаються ці категорії і наскільки глибока ієрархія - залежить від самої мови.
Область видимості
Функція і клас можуть бути визначені, як неявний простір імен, складно пов'язані з видимістю, доступністю і періодом життя об'єкта .
C#
У мові C # існують простори імен, які вживаються аналогічно C ++.
Python
У Python ідея просторів імен реалізована у модулях. (Так само, як і у пакетах Java)
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[1].
Common Lisp
У стандартному синтаксисі Common Lisp є табличні простори імен, які реалізуються через систему пакетів[2]. Необхідно вказати назву ідентифікатора (символу) для використання, а саме: повну назву (назва пакету, двокрапка та назва самого символу)[3].
У Allegro Common Lisp реалізовано нестандартне розширення Common Lisp - ієрархічний простір імен, де пакети розділяються використанням крапки, у стилі Java , а ідентифікатор від пакетів відокремлюється двокрапкою. Також, можливі звернення до суміжних вузлів в ієрархії просторів імен через посилання до відносних шляхів, використовуючи двокрапку[4]. Простори імен у Common Lisp є динамічними - вони створюються, наповнюються і знищуються під час виконання програми, [ джерело? ] хоча здебільшого застосовується декларативна форма їх опису за допомогою форми defpackage
[5] .
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) до елементів без вказівок на ім'я модуля.
UnuseModule Count ; Скасування дії UseModule.
Для отримання доступу елементів модуля з іншого модуля або глобального простору, необхідно вказати ім'я модуля і його елемент. Наприклад: Count :: x. Також, можна використати команду UseModule, яка дозволяє відобразити всі видимі елементи модуля до поточного простору. Команда UnuseModule скасовує цю дію. Одночасне відображення видимих елементів декількох модулів можливе, за умови попереджання проблеми конфлікту імен. Припустимо, що у проекті є модулі з іменами x, y і z.
UseModule x
UseModule y
; Код.
UseModule z
; Ще код.
UnuseModule y
; Ще код.
UnuseModule x
UnuseModule z
Цей приклад відображає можливість відображання у поточний простір декількох модулів, а також особливість, що не важлива послідовність відображення елементів модулів і його скасування.
Мови програмування без власної підтримки просторів імен простору можуть емулюватися розширенням, використовуючи угоди про найменування ідентифікаторів Прикладом цього є, бібліотеки мови С, такі як Libpng, часто використовують фіксований префікс для всіх функцій і змінних, що є частиною їх зовнішнього інтерфейсу. Libpng підтримує зовнішні ідентифікатори, такі як:
- png_create_write_struct
- png_get_signature
- png_read_row
- png_set_invalid
Це надає обґрунтовану гарантію, що ідентифікатори будуть унікальні і, таким чином, можуть бути використані у великих програмах без побоювання колізії імен ідентифікаторів .
Далі перераховані недоліки емуляції просторів імен
- Відсутній нормально функціонуючий облік вкладених просторів; ідентифікатори подовжуються занадто.
- Програмісти/організації можуть використати різко несумісні угоди про найменування, тим самим потенційно провокуючи велику заплутаність.
- Складні операції чи операції запиту над групами ідентифікаторів, заснованих на просторі імен, де вони оголошені, обробляються занадто неоптимально, інколи, взагалі нездійсненні.
- Усі виклики ідентифікаторів повинні здійснюватися з повним ім'ям просторів (англ) Мови з безпосередньою підтримкою просторів імен, зазвичай, надають програмісту можливість попередньо оголошувати, що він хоче використовувати деякі (а то і всі разом) ідентифікатори у програмі тільки з одного простору, які вони згодом можуть використовувати без вказівки належності до простору.
Примітки
- PHP: Використання простору імен: основи — Manual
- Packages (англ.). www.cs.northwestern.edu. Процитовано 23 грудня 2018.
- Source Code Organisation. lispmethods.com. Процитовано 23 грудня 2018.
- Hierarchical Packages (англ.). franz.com. Процитовано 10 червня 2017.
- CLHS: Macro DEFPACKAGE. www.lispworks.com. Процитовано 10 червня 2017.