Пространство имен
В вычислительной технике пространство имен — это набор знаков ( имен ), которые используются для идентификации и обращения к объектам различных видов. Пространство имен гарантирует, что все объекты данного набора имеют уникальные имена, чтобы их можно было легко идентифицировать .
Пространства имен обычно структурируются как иерархии, позволяющие повторно использовать имена в разных контекстах. В качестве аналогии рассмотрим систему именования людей , в которой у каждого человека есть имя, а также фамилия, общая с его родственниками. Если имена членов семьи уникальны только внутри каждой семьи, то каждого человека можно однозначно идентифицировать по сочетанию имени и фамилии; есть только одна Джейн Доу, хотя Джейн может быть много. В пространстве имен семьи Доу достаточно просто «Джейн», чтобы однозначно обозначить этого человека, тогда как в «глобальном» пространстве имен всех людей необходимо использовать полное имя.
Яркими примерами пространств имен являются файловые системы , которые присваивают имена файлам. [1] Некоторые языки программирования организуют свои переменные и подпрограммы в пространствах имен. [2] [3] [4] Компьютерные сети и распределенные системы присваивают имена ресурсам, таким как компьютеры , принтеры , веб-сайты и удаленные файлы. Операционные системы могут разделять ресурсы ядра по изолированным пространствам имен для поддержки контейнеров виртуализации .
Аналогичным образом иерархические файловые системы организуют файлы в каталогах. Каждый каталог представляет собой отдельное пространство имен, поэтому каталоги «Letters» и «Invoices» могут содержать файл «to_jane».
В компьютерном программировании пространства имен обычно используются с целью группировки символов и идентификаторов вокруг определенной функции и во избежание конфликтов имен между несколькими идентификаторами, имеющими одно и то же имя.
В сети система доменных имен организует веб-сайты (и другие ресурсы) в иерархические пространства имен .
Конфликты имен
[ редактировать ]Имена элементов определяются разработчиком. Это часто приводит к конфликту при попытке смешивания XML-документов из разных XML-приложений.
Этот XML содержит информацию таблицы HTML :
<table> <tr> <td>Apples</td> <td>Oranges</td> </tr></table>
Этот XML содержит информацию о таблице (т. е. предмете мебели):
<table> <name>Mahogany Coffee Table</name> <width>80</width> <length>120</length></table>
Если бы эти фрагменты XML были добавлены вместе, возник бы конфликт имен. Оба содержат <table>...</table>
элемент, но элементы имеют разное содержание и значение.
Анализатор XML не знает, как справиться с этими различиями.
Решение через префикс
[ редактировать ]Конфликтов имен в XML можно легко избежать, используя префикс имени.
Следующий XML-код различает информацию о HTML-таблице и мебели с помощью префиксов «h» и «f» в начале элементов.
<h:table> <h:tr> <h:td>Apples</h:td> <h:td>Oranges</h:td> </h:tr></h:table><f:table> <f:name>Mahogany Coffee Table</f:name> <f:width>80</f:width> <f:length>120</f:length></f:table>
Система именования
[ редактировать ]Имя в пространстве имен состоит из имени пространства имен и локального имени. [5] [6] Имя пространства имен обычно применяется как префикс к локальному имени.
В расширенной форме Бэкуса – Наура :
name = <namespace name> separator <local name>
Когда локальные имена используются сами по себе, разрешение имен используется для определения того, какое конкретное имя (если таковое имеется) ссылается на какое-то конкретное локальное имя.
Примеры
[ редактировать ]Контекст | Имя | Имя пространства имен | Местное название |
---|---|---|---|
Путь | /home/user/readme.txt | /home/user (каталог) | readme.txt (имя файла) |
Доменное имя | www.example.com | example.com (доменное имя) | www (листовое доменное имя) |
С++ | станд::массив | std (пространство имен C++) | массив (структура) |
ООН/ЛОКОД | США Нью-Йорк | США (страна или территория) | Нью-Йорк (местность) |
XML | xmlns:xhtml=" http://www.w3.org/1999/xhtml " <xhtml:тело> | xhtml (ранее объявленное пространство имен XML xhtml=" http://www.w3.org/1999/xhtml ") | тело (элемент) |
Перл | $DBI::errstr | $DBI (модуль Perl) | ошибка (переменная) |
Ява | java.util.Date | java.util (пространство имен Java) | Дата (класс) |
Единое имя ресурса (URN) | урна:nbn:fi-fe19991055 | urn:nbn (национальные библиографические номера) | fi-fe19991055 |
Ручка системы | 10.1000/182 | 10 (дескриптор полномочий наименования) | 1000/182 (обрабатывать локальное имя) |
Идентификатор цифрового объекта | 10.1000/182 | 10.1000 (издатель) | 182 (публикация) |
MAC-адрес | 01-23-45-67-89-аб | 23-01-45 ( организационно уникальный идентификатор ) | 67-89-ab (специфичный для NIC) |
PCI-идентификатор | 1234 АБВД | 1234 (идентификатор поставщика) | abcd (идентификатор устройства) |
USB-ВИД/ПИД | 2341 003ф [7] | 2341 (идентификатор поставщика) | 003f (идентификатор продукта) |
СПАРКЛ | дбр:Сидней | dbr (ранее объявленная онтология, например, путем указания @prefix dbr: < http://dbpedia.org/resource/ >) | Сидней |
Делегация
[ редактировать ]Делегирование ответственности между сторонами важно в реальных приложениях, таких как структура Всемирной паутины. Пространства имен позволяют делегировать присвоение идентификатора нескольким организациям, выдающим имена, сохраняя при этом глобальную уникальность. [8] Центральный орган регистрации регистрирует назначенные имена пространств имен . Каждое имя пространства имен выделяется организации, которая впоследствии несет ответственность за присвоение имен в выделенном им пространстве имен. Эта организация может быть организацией, выдающей имена, которая сама присваивает имена , или другим органом регистрации , который в дальнейшем делегирует части своего пространства имен различным организациям.
Иерархия
[ редактировать ]Схема именования, которая позволяет делегировать пространства имен третьим сторонам, представляет собой иерархическое пространство имен .
Иерархия является рекурсивной, если синтаксис имен пространств имен одинаков для каждого подделегирования. Примером рекурсивной иерархии является система доменных имен .
Примером нерекурсивной иерархии является единое имя ресурса, представляющее номер Управления присвоения номеров Интернета (IANA).
Реестр | Регистратор | Пример идентификатора | Имя пространства имен | Пространство имен |
---|---|---|---|---|
Единое имя ресурса (URN) | Управление по присвоению номеров в Интернете | урна:isbn:978-3-16-148410-0 | урна | Формальное пространство имен URN |
Формальное пространство имен URN | Управление по присвоению номеров в Интернете | урна:isbn:978-3-16-148410-0 | ISBN | Международные стандартные номера книг как единые названия ресурсов |
Международный артикул (EAN) | ГС1 | 978-3-16-148410-0 | 978 | Книжная страна |
Международный стандартный номер книги (ISBN) | Международное агентство ISBN | 3-16-148410-Х | 3 | Немецкоязычные страны |
Код немецкого издателя | Агентство по стандартам книжного рынка | 3-16-148410-Х | 16 | Мор Зибек |
Пространство имен и область действия
[ редактировать ]Имя пространства имен может обеспечивать контекст ( область действия в информатике) для имени, и эти термины иногда используются как взаимозаменяемые. Однако контекст имени может также зависеть от других факторов, таких как место, где оно встречается, или синтаксис имени.
Без пространства имен | С пространством имен | |
---|---|---|
Локальная область действия | Номерной знак транспортного средства | Стандарт иерархии файловой системы |
Глобальная область действия | Универсальный уникальный идентификатор | Система доменных имен |
В языках программирования
[ редактировать ]Для многих языков программирования пространство имен является контекстом для их идентификаторов . В операционной системе примером пространства имен является каталог. Каждое имя в каталоге однозначно идентифицирует один файл или подкаталог. [9]
Как правило, имена в пространстве имен не могут иметь более одного значения; то есть разные значения не могут использовать одно и то же имя в одном пространстве имен. Пространство имен также называется контекстом , поскольку одно и то же имя в разных пространствах имен может иметь разные значения, каждое из которых соответствует своему пространству имен.
Ниже приведены другие характеристики пространств имен:
- Имена в пространстве имен могут представлять объекты, а также концепции , будь то пространство имен — естественный или этнический язык , искусственный язык , техническая терминология профессии, диалект , социолект или искусственный язык (например, язык программирования ).
- В языке программирования Java идентификаторы, которые появляются в пространствах имен, имеют короткое (локальное) имя и уникальное длинное «полное» имя для использования вне пространства имен.
- Некоторые компиляторы (для таких языков, как C++ ) объединяют пространства имен и имена для внутреннего использования в компиляторе в процессе, называемом искажением имен .
Помимо технического использования абстрактного языка, как описано выше, в некоторых языках есть определенное ключевое слово, используемое, помимо прочего, для явного управления пространством имен. Ниже приведен пример пространства имен в C++:
#include <iostream>// This is how one brings a name into the current scope. In this case, it's// bringing them into global scope.using std::cout;using std::endl;namespace box1 { int box_side = 4;}namespace box2 { int box_side = 12;}int main() { int box_side = 42; cout << box1::box_side << endl; // Outputs 4. cout << box2::box_side << endl; // Outputs 12. cout << box_side << endl; // Outputs 42.}
Соображения информатики
[ редактировать ]Пространство имен в информатике (иногда также называемое областью имен ) — это абстрактный контейнер или среда, созданная для хранения логической группировки уникальных идентификаторов или символов (т. е. имен). Идентификатор, определенный в пространстве имен, связан только с этим пространством имен. Один и тот же идентификатор может быть независимо определен в нескольких пространствах имен. То есть идентификатор, определенный в одном пространстве имен, может иметь или не иметь то же значение, что и тот же идентификатор, определенный в другом пространстве имен. Языки, поддерживающие пространства имен, определяют правила, определяющие, к какому пространству имен принадлежит идентификатор (а не его определение). [10]
Эту концепцию можно проиллюстрировать аналогией. Представьте себе, что две компании, X и Y, присваивают своим сотрудникам идентификационные номера. У X не должно быть двух сотрудников с одинаковым идентификационным номером, как и у Y; однако использование одного и того же идентификационного номера в обеих компаниях не является проблемой. Например, если Билл работает в компании X, а Джейн работает в компании Y, то для каждого из них не проблема быть сотрудником № 123. В этой аналогии идентификационный номер является идентификатором, а компания служит пространством имен. Это не вызывает проблем, если один и тот же идентификатор идентифицирует разных людей в каждом пространстве имен.
В больших компьютерных программах или документах обычно используются сотни или тысячи идентификаторов. Пространства имен (или аналогичный метод, см. Эмуляция пространств имен ) предоставляют механизм сокрытия локальных идентификаторов. Они предоставляют средства группировки логически связанных идентификаторов в соответствующие пространства имен, тем самым делая систему более модульной .
Устройства хранения данных и многие современные языки программирования поддерживают пространства имен. Устройства хранения используют каталоги (или папки) в качестве пространств имен. Это позволяет хранить на устройстве два файла с одинаковым именем, если они хранятся в разных каталогах. В некоторых языках программирования (например, C++ , Python ) идентификаторы, именующие пространства имен, сами связаны с включающим пространством имен. Таким образом, в этих языках пространства имен могут вкладываться, образуя дерево пространств имен . В корне этого дерева находится безымянное глобальное пространство имен .
Использование на обычных языках
[ редактировать ]С
[ редактировать ]можно использовать анонимные структуры в качестве пространств имен, В C начиная с C99 .
// helper.cstatic int _add(int a, int b) { return a + b;}const struct { double pi; int (*add) (int, int);} helper = { 3.14, _add };// helper.hconst struct { double pi; int (*add) (int, int);} helper;// main.c#include <stdio.h>#include "helper.h"int main(){ printf("3 + 2 = %d\n", helper.add(3, 2)); printf("pi is %f\n", helper.pi);}
С++
[ редактировать ]В C++ пространство имен определяется блоком пространства имен. [11]
namespace abc { int bar;}
Внутри этого блока идентификаторы могут использоваться точно так, как они объявлены. За пределами этого блока спецификатор пространства имен должен иметь префикс. Например, за пределами namespace abc
, bar
должно быть написано abc::bar
для доступа. В C++ есть еще одна конструкция, которая делает это многословие ненужным. Добавив строку
using namespace abc;
к фрагменту кода, префиксу abc::
больше не нужен.
Идентификаторы, которые не объявлены явно в пространстве имен, считаются находящимися в глобальном пространстве имен.
int foo;
Эти идентификаторы можно использовать точно так, как они объявлены, или, поскольку глобальное пространство имен не имеет имени, спецификатор пространства имен ::
может иметь префикс. Например, foo
также можно написать ::foo
.
Разрешение пространства имен в C++ является иерархическим. Это означает, что внутри гипотетического пространства имен food::soup
, идентификатор chicken
относится к food::soup::chicken
. Если food::soup::chicken
не существует, тогда он относится к food::chicken
. Если ни один food::soup::chicken
ни food::chicken
существовать, chicken
относится к ::chicken
, идентификатор в глобальном пространстве имен.
Пространства имен в C++ чаще всего используются во избежание конфликтов имен . Хотя пространства имен широко используются в последнем коде C++, в большинстве старых кодов эта возможность не используется, поскольку ее не существовало в ранних версиях языка. Например, вся стандартная библиотека C++ определена внутри namespace std
, но до стандартизации многие компоненты изначально находились в глобальном пространстве имен. Программист может вставить using
директива для обхода требований разрешения пространства имен и обеспечения обратной совместимости со старым кодом, который ожидает, что все идентификаторы будут находиться в глобальном пространстве имен. Однако использование using
Директива по причинам, отличным от обратной совместимости (например, удобство), считается противоречащей хорошей практике написания кода.
Ява
[ редактировать ]В Java идея пространства имен воплощена в Java-пакетах . Весь код принадлежит пакету, хотя этот пакет не обязательно должен иметь явное имя. Доступ к коду из других пакетов осуществляется путем добавления имени пакета перед соответствующим идентификатором, например class String
в package java.lang
можно назвать java.lang.String
(это известно как полное имя класса ). Как и C++, Java предлагает конструкцию, благодаря которой нет необходимости вводить имя пакета ( import
). Однако некоторые функции (например, отражение ) требуют от программиста использования полного имени.
В отличие от C++, пространства имен в Java не являются иерархическими с точки зрения синтаксиса языка. Однако пакеты именуются иерархически. Например, все пакеты, начинающиеся с java
являются частью платформы Java — пакета java.lang
содержит классы, основные для языка, и java.lang.reflect
содержит основные классы, специально относящиеся к отражению.
В Java (а также Ada , C# и других) пространства имен/пакеты выражают семантические категории кода. Например, в C# namespace System
содержит код, предоставляемый системой ( .NET Framework ). Насколько специфичны эти категории и насколько глубоки их иерархии, различаются от языка к языку.
функций и классов Области можно рассматривать как неявные пространства имен, которые неразрывно связаны с видимостью, доступностью и временем жизни объекта .
С#
[ редактировать ]Пространства имен широко используются в языке C#. Все классы .NET Framework организованы в пространства имен, чтобы их можно было использовать более четко и избежать хаоса. Более того, пользовательские пространства имен широко используются программистами как для организации своей работы, так и для предотвращения конфликтов имен .При ссылке на класс следует указать либо его полное имя, что означает пространство имен, за которым следует имя класса,
System.Console.WriteLine("Hello World!");int i = System.Convert.ToInt32("123");
или добавьте оператор использования . Это устраняет необходимость указывать полное имя всех классов в этом пространстве имен.
using System;Console.WriteLine("Hello World!");int i = Convert.ToInt32("123");
В приведенных выше примерах System — это пространство имен, а Console и Convert — это классы, определенные в System .
Питон
[ редактировать ]В Python пространства имен определяются отдельными модулями, а поскольку модули могут содержаться в иерархических пакетах, пространства имен также являются иерархическими. [12] [13] Обычно, когда модуль импортируется, имена, определенные в модуле, определяются через пространство имен этого модуля, и доступ к ним из вызывающих модулей осуществляется с использованием полного имени.
# assume modulea defines two functions : func1() and func2() and one class : Class1import ModuleaModulea.func1()Modulea.func2()a = Modulea.Class1()
The from ... import ...
Оператор можно использовать для вставки соответствующих имен непосредственно в пространство имен вызывающего модуля, и к этим именам можно получить доступ из вызывающего модуля без уточненного имени:
# assume Modulea defines two functions : func1() and func2() and one class : Class1from Modulea import func1func1()func2() # this will fail as an undefined name, as will the full name Modulea.func2()a = Class1() # this will fail as an undefined name, as will the full name Modulea.Class1()
Поскольку при этом имена импортируются напрямую (без уточнений), существующие имена могут быть перезаписаны без каких-либо предупреждений.
Особой формой заявления является from ... import *
который импортирует все имена, определенные в именованном пакете, непосредственно в пространство имен вызывающего модуля. Использование этой формы импорта, хотя и поддерживается в языке, обычно не рекомендуется, поскольку оно загрязняет пространство имен вызывающего модуля и приводит к перезаписи уже определенных имен в случае конфликта имен. [14]
Python также поддерживает import x as y
как способ предоставления псевдонима или альтернативного имени для использования вызывающим модулем:
import numpy as npa = np.arange(1000)
пространство имен XML
[ редактировать ]В XML спецификация пространства имен XML позволяет именам элементов и атрибутов в документе XML быть уникальными, аналогично роли пространств имен в языках программирования. Используя пространства имен XML, документы XML могут содержать имена элементов или атрибутов из более чем одного словаря XML.
PHP
[ редактировать ]Пространства имен были введены в PHP начиная с версии 5.3. Можно избежать конфликта имен классов, функций и переменных.В PHP пространство имен определяется блоком пространства имен.
# File phpstar/foobar.phpnamespace phpstar;class FooBar{ public function foo(): void { echo 'Hello world, from function foo'; } public function bar(): void { echo 'Hello world, from function bar'; }}
Мы можем ссылаться на пространство имен PHP следующими способами:
# File index.php# Include the fileinclude "phpstar/foobar.php";# Option 1: directly prefix the class name with the namespace$obj_foobar = new \phpstar\FooBar();# Option 2: import the namespaceuse phpstar\FooBar;$obj_foobar = new FooBar();# Option 2a: import & alias the namespaceuse phpstar\FooBar as FB;$obj_foobar = new FB();# Access the properties and methods with regular way$obj_foobar->foo();$obj_foobar->bar();
Эмуляция пространств имен
[ редактировать ]В языках программирования, в которых отсутствует языковая поддержка пространств имен, пространства имен можно в некоторой степени эмулировать с помощью соглашения об именовании идентификаторов . Например, библиотеки C , такие как libpng, часто используют фиксированный префикс для всех функций и переменных, которые являются частью их открытого интерфейса. Libpng предоставляет такие идентификаторы, как:
png_create_write_structpng_get_signaturepng_read_rowpng_set_invalid
Это соглашение об именах обеспечивает разумную гарантию того, что идентификаторы уникальны и, следовательно, могут использоваться в более крупных программах без конфликтов имен . [15] Аналогично, многие пакеты, изначально написанные на Фортране (например, BLAS , LAPACK ), резервируют первые несколько букв имени функции, чтобы указать, к какой группе она принадлежит.
Эта технология имеет ряд недостатков:
- Он плохо масштабируется во вложенных пространствах имен; идентификаторы становятся слишком длинными, поскольку все виды использования идентификаторов должны полностью соответствовать пространству имен .
- Отдельные лица или организации могут использовать противоречивые соглашения об именах, что потенциально может привести к нежелательной путанице.
- Составные или «основанные на запросах» операции над группами идентификаторов, основанные на пространствах имен, в которых они объявлены, становятся громоздкими или невозможными.
- В языках с ограниченной длиной идентификатора использование префиксов ограничивает количество символов, которые можно использовать для идентификации того, что делает функция. Это особая проблема для пакетов, изначально написанных на FORTRAN 77 , который предлагал только 6 символов на идентификатор. Например, имя BLAS функции
DGEMM
указывает, что она работает с числами двойной точности («D») и общими матрицами («GE»), и только последние два символа показывают, что она на самом деле делает: умножение матрицы на матрицу («MM»).
Есть несколько преимуществ:
- Для поиска имен в файлах исходного кода не требуется никаких специальных программных инструментов. Достаточно простой программы, такой как grep .
- Конфликтов имен пространств имен нет.
- Нет необходимости в искажении имен и, следовательно, нет потенциальных проблем несовместимости.
См. также
[ редактировать ]- 11-значный пункта доставки почтовый индекс
- Биномиальная номенклатура (род-вид в биологии )
- Химическая номенклатура
- Десятичная классификация Дьюи
- Идентификатор цифрового объекта
- Система доменных имен
- Четвертая стена
- Идентичность (объектно-ориентированное программирование)
- Классификация Библиотеки Конгресса
- Звездные каталоги и соглашения об астрономических названиях
- Нарушение уровня абстракции
- пространство имен XML
- Поиск имени в зависимости от аргумента
Ссылки
[ редактировать ]- ^ Адья, Атул; Болоски, Уильям; Кастро, Мигель; Чермак, Джеральд; Чайкен, Ронни; Дусер, Джон; Хауэлл, Джон; Лорх, Джейкоб; Теймер, Марвин; Ваттенхофер, Роджер (2002). FARSITE: Федеративное, доступное и надежное хранилище для неполностью доверенной среды (PDF) . Учеб. USENIX симп. по проектированию и внедрению операционных систем. Архивировано из оригинала (PDF) 28 июля 2010 г.
Основная конструкция, установленная файловой системой, — это иерархическое пространство имен каталогов, которое является логическим хранилищем файлов.
- ^ «Часто задаваемые вопросы по C#: что такое пространство имен» . C# Интернет-сеть. Архивировано из оригинала 20 октября 2013 г. Проверено 23 февраля 2010 г.
Пространство имен — это не что иное, как группа сборок, классов или типов. Пространство имен действует как контейнер (например, папка на диске) для классов, организованных в группы, обычно в зависимости от функциональности. пространств имен C# Синтаксис позволяет вкладывать пространства имен.
- ^ «Обзор пространств имен в PHP» . Руководство по PHP .
Что такое пространства имен? В самом широком определении пространства имен — это способ инкапсуляции элементов. Во многих местах это можно рассматривать как абстрактную концепцию. Например, в любой операционной системе каталоги служат для группировки связанных файлов и служат пространством имен для файлов внутри них.
- ^ «Создание и использование пакетов» . Java-документация . Оракул.
Пакет — это группа связанных типов, обеспечивающая защиту доступа и управление пространством имен. Обратите внимание, что типы относятся к классам , интерфейсам , перечислениям и типам аннотаций. Типы перечислений и аннотаций представляют собой особые виды классов и интерфейсов соответственно, поэтому в этом уроке типы часто называются просто классами и интерфейсами.
[ нужен лучший источник ] - ^ Основная рабочая группа XML (8 декабря 2009 г.). «Пространства имен в XML 1.0 (третье издание)» . W3C . Проверено 30 марта 2012 г.
- ^ Моутс, Райан (май 1997 г.). «Синтаксис» . Синтаксис URN . IETF . п. 1. сек. 2. дои : 10.17487/RFC2141 . РФК 2141 . Проверено 30 марта 2012 г.
- ^ Стивен Дж. Гауди. «Список USB-идентификаторов» .2013.
- ^ Соллинз и Масинтер (декабрь 1994 г.). «Требования к функциональным возможностям» . Функциональные требования к унифицированным именам ресурсов . IETF . п. 3. сек. 2. дои : 10.17487/RFC1731 . РФК 1731 . Проверено 30 марта 2012 г.
- ^ «Часто задаваемые вопросы по C#: что такое пространство имен» . Интернет-сеть C# . Архивировано из оригинала 20 октября 2013 года . Проверено 23 февраля 2010 г.
Например, [в Windows ] для доступа к встроенным классам и членам ввода-вывода (I/O) используйте пространство имен System.IO. Или для доступа к классам и членам, связанным с Интернетом, используйте пространство имен System.Web.
- ^ «Пространство имен — это «логическая группа имен, используемых в программе». » . Вебопедия.com. 10 апреля 2002 года . Проверено 26 июля 2011 г.
- ^ «Пространства имен позволяют группировать сущности, такие как классы, объекты и функции, под именем» . Cplusplus.com . Проверено 26 июля 2011 г.
- ^ «6. Модули» . Учебник по Python . Фонд программного обеспечения Python . Проверено 25 октября 2010 г.
- ^ «Области видимости и пространства имен Python» . Docs.python.org . Проверено 26 июля 2011 г.
- ^ https://docs.python.org/3/tutorial/modules.html «в целом практика импорта * из модуля или пакета не одобряется»
- ^ Дэнни Калев. «Почему я ненавижу пространства имен» . Архивировано из оригинала 9 июля 2016 г.
{{cite web}}
: CS1 maint: bot: исходный статус URL неизвестен ( ссылка )