Управление доступом
Управляйте видимостью кода с помощью объявления, файла и модуля.
Управление доступом ограничивает доступ к частям вашего кода из кода в других исходных файлах и модулях. Эта функция позволяет скрыть детали реализации вашего кода и указать предпочтительный интерфейс, через который этот код может быть доступен и использован.
Вы можете назначить определённые уровни доступа отдельным типам (классам, структурам и перечислениям), а также свойствам, методам, инициализаторам и подстрокам, относящимся к этим типам. Протоколы могут быть ограничены определённым контекстом, как и глобальные константы, переменные и функции.
Помимо предоставления различных уровней управления доступом, Swift уменьшает необходимость в явном указании уровней доступа, предоставляя значения по умолчанию для типовых сценариев. Действительно, если вы пишете приложение с одним целевым устройством, вам, возможно, не потребуется указывать явные уровни управления доступом вообще.
Примечание: различные аспекты вашего кода, к которым можно применять контроль доступа (свойства, типы, функции и т. д.), в следующих разделах для краткости называются «сущностями».
Модули, исходные файлы и пакеты
Модель управления доступом Swift основана на концепции модулей, исходных файлов и пакетов.
Модуль — это единица распространения кода — фреймворк или приложение, которое создаётся и распространяется как единое целое и может быть импортирован другим модулем с помощью ключевого слова Swift import.
Каждая целевая сборка (например, пакет приложения или фреймворк) в Xcode обрабатывается как отдельный модуль в Swift. Если вы группируете части кода вашего приложения в автономный фреймворк — возможно, чтобы инкапсулировать и повторно использовать этот код в нескольких приложениях — то всё, что вы определяете в этом фреймворке, будет частью отдельного модуля при его импорте и использовании в приложении или в другом фреймворке.
Исходный файл — это отдельный исходный файл Swift внутри модуля (по сути, отдельный файл в приложении или фреймворке). Хотя принято определять отдельные типы в отдельных исходных файлах, один исходный файл может содержать определения для нескольких типов, функций и т. д.
Пакет — это группа модулей, которые вы разрабатываете как единое целое. Вы определяете модули, образующие пакет, в процессе настройки системы сборки, а не в вашем исходном коде Swift. Например, если вы используете Swift Package Manager для сборки кода, вы определяете пакет в вашем файле Package.swift с помощью API из модуля PackageDescription, а если вы используете Xcode, вы указываете имя пакета в настройке сборки «Идентификатор доступа к пакету».
Уровни доступа
Swift предоставляет шесть различных уровней доступа для сущностей в вашем коде. Эти уровни доступа относительны к исходному файлу, в котором определена сущность, к модулю, к которому принадлежит этот исходный файл, и к пакету, к которому принадлежит модуль.
- Открытый доступ и публичный доступ позволяют использовать сущности в любом исходном файле из их определяющего модуля, а также в исходном файле из другого модуля, который импортирует определяющий модуль. Вы обычно используете открытый или публичный доступ при указании публичного интерфейса фреймворка. Разница между открытым и публичным доступом описана ниже.
- Доступ к пакету позволяет использовать сущности во всех исходных файлах из своего определяющего пакета, но не в любом исходном файле за пределами этого пакета. Вы обычно используете доступ к пакету внутри приложения или фреймворка, структурированного в несколько модулей.
- Внутренний доступ позволяет использовать сущности в любом исходном файле из определяющего модуля, но не в любом исходном файле за пределами этого модуля. Вы обычно используете внутренний доступ при определении внутренней структуры приложения или фреймворка.
- Файлово-частный доступ ограничивает использование сущности её определяющим исходным файлом. Используйте файл-частный доступ, чтобы скрыть детали реализации определённой функциональности, когда эти детали используются в рамках всего файла.
- Частный доступ ограничивает использование сущности объявляющей её декларацией и расширениями этой декларации, которые находятся в том же файле. Используйте частный доступ, чтобы скрыть детали реализации определённой функциональности, когда эти детали используются только внутри одной декларации.
Открытый доступ — это наивысший (наименее ограниченный) уровень доступа, а частный доступ — это наименьший (самый ограниченный) уровень доступа.
Открытый доступ применяется только к классам и членам класса, и он отличается от публичного доступа тем, что позволяет коду за пределами модуля наследовать и переопределять, как обсуждается ниже в <doc:AccessControl#Subclassing>. Пометка класса как открытого явно указывает, что вы учли влияние кода из других модулей, использующих этот класс в качестве базового класса, и что вы соответствующим образом спроектировали код своего класса.
Руководящий принцип уровней доступа
Уровни доступа в Swift следуют общему руководящему принципу: ни одна сущность не может быть определена в терминах другой сущности, имеющей более низкий (более ограниченный) уровень доступа.
Например:
- Публичная переменная не может быть определена как имеющая внутренний, файлово-частный или частный тип, поскольку тип может быть недоступен везде, где используется публичная переменная.
- Функция не может иметь более высокий уровень доступа, чем типы её параметров и возвращаемый тип, поскольку функция может быть использована в ситуациях, когда составляющие типы недоступны окружающему коду.
Конкретные последствия этого руководящего принципа для разных аспектов языка подробно рассматриваются ниже.
Уровни доступа по умолчанию
Все сущности в вашем коде (с несколькими специфическими исключениями, описанными позже в этой главе) имеют уровень доступа по умолчанию «внутренний», если вы не укажете явный уровень доступа самостоятельно. В результате во многих случаях вам не нужно указывать явный уровень доступа в вашем коде.
Уровни доступа для приложений с одной целевой платформой
Когда вы пишете простое приложение с одной целевой платформой, код вашего приложения обычно содержится в приложении и не должен быть доступен за пределами модуля приложения. Уровень доступа по умолчанию «внутренний» уже соответствует этому требованию. Поэтому вам не нужно указывать пользовательский уровень доступа. Однако вы можете отметить некоторые части вашего кода как «файл-частный» или «частный», чтобы скрыть их реализацию от другого кода внутри модуля приложения.
Уровни доступа для фреймворков
При разработке фреймворка помечайте публичный интерфейс этого фреймворка как открытый или публичный, чтобы его можно было просматривать и к нему можно было получить доступ из других модулей, например, приложения, которое импортирует фреймворк. Этот публичный интерфейс является интерфейсом программирования приложения (API) для фреймворка.
Примечание: любые внутренние детали реализации вашего фреймворка всё ещё могут использовать уровень доступа по умолчанию «внутренний» или могут быть помечены как «частные» или «файл-частные», если вы хотите скрыть их от других частей внутреннего кода фреймворка. Вы должны пометить сущность как «открытую» или «публичную» только в том случае, если хотите, чтобы она стала частью API вашего фреймворка.
Уровни доступа для целевых платформ юнит-тестирования
Когда вы пишете приложение с целевой платформой юнит-тестирования, код вашего приложения должен быть доступен этому модулю для тестирования. По умолчанию доступны только сущности, помеченные как открытые или публичные, для других модулей. Однако целевая платформа юнит-тестирования может получить доступ к любой внутренней сущности, если вы пометите объявление импорта для модуля продукта атрибутом @testable и скомпилируете этот модуль продукта с включённым тестированием.
Синтаксис управления доступом
Определите уровень доступа для сущности, поместив один из open, public, internal, fileprivate или private модификаторов в начале объявления сущности.
open class SomeOpenClass {}
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
open var someOpenVariable = 0
public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {} Если не указано иное, уровень доступа по умолчанию — внутренний, как описано в <doc:AccessControl#Default-Access-Levels>. Это означает, что SomeInternalClass и someInternalConstant могут быть написаны без явного модификатора уровня доступа и всё равно будут иметь уровень доступа «внутренний»:
class SomeInternalClass {} // implicitly internal
let someInternalConstant = 0 // implicitly internal Пользовательские типы
Если вы хотите указать явный уровень доступа для пользовательского типа, сделайте это в момент определения типа. Новый тип затем может быть использован там, где это разрешено его уровнем доступа. Например, если вы определите файл-частный класс, этот класс может использоваться только как тип свойства или как параметр или возвращаемый тип функции в исходном файле, в котором определён файл-частный класс.
Уровень контроля доступа типа также влияет на уровень доступа по умолчанию для членов этого типа (свойства, методы, инициализаторы и подстроки). Если вы определите уровень доступа типа как частный или файл-частный, уровень доступа по умолчанию для его членов также будет частный или файл-частный. Если вы определите уровень доступа типа как внутренний или публичный (или используете уровень доступа по умолчанию «внутренний» без явного указания уровня доступа), уровень доступа по умолчанию для членов типа будет внутренний.
Важно: публичный тип по умолчанию имеет внутренние члены, а не публичные. Если вы хотите, чтобы член типа был публичным, вы должны явно пометить его как таковой. Это требование гарантирует, что публичный API для типа — это то, что вы публикуете осознанно, и предотвращает случайное представление внутренней работы типа как публичного API.
public class SomePublicClass { // explicitly public class
public var somePublicProperty = 0 // explicitly public class member
var someInternalProperty = 0 // implicitly internal class member
fileprivate func someFilePrivateMethod() {} // explicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
class SomeInternalClass { // implicitly internal class
var someInternalProperty = 0 // implicitly internal class member
fileprivate func someFilePrivateMethod() {} // explicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
fileprivate class SomeFilePrivateClass { // explicitly file-private class
func someFilePrivateMethod() {} // implicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
private class SomePrivateClass { // explicitly private class
func somePrivateMethod() {} // implicitly private class member
} Кортежи
Уровень доступа для кортежа — это наиболее ограниченный уровень доступа всех типов, используемых в этом кортеже. Например, если вы создаёте кортеж из двух разных типов, один с внутренним доступом, а другой с частным, уровень доступа для этого кортежа будет частным.
Примечание: типы кортежей не имеют самостоятельного определения, как классы, структуры, перечисления и функции. Уровень доступа для типа кортежа определяется автоматически из типов, составляющих кортеж, и не может быть указан явно.
Типы функций
Уровень доступа для типа функции вычисляется как наиболее ограниченный уровень доступа типов параметров и возвращаемого типа функции. Вы должны указать уровень доступа явно как часть определения функции, если вычисленный уровень доступа функции не соответствует контекстному значению по умолчанию.
В примере ниже определена глобальная функция someFunction(), без указания конкретного модификатора уровня доступа для самой функции. Можно ожидать, что эта функция будет иметь уровень доступа по умолчанию «внутренний», но это не так. Фактически, someFunction() не будет компилироваться в том виде, как написано ниже:
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
} Возвращаемый тип функции — это кортеж, составленный из двух пользовательских классов, определённых выше в <doc:AccessControl#Custom-Types>. Один из этих классов определён как внутренний, а другой — как частный. Следовательно, общий уровень доступа для составного типа кортежа — частный (минимальный уровень доступа составляющих кортежа типов).
Поскольку тип возвращаемого значения функции является закрытым, вам необходимо пометить общий уровень доступа функции модификатором private для того, чтобы объявление функции было допустимым:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
} Недопустимо помечать определение someFunction() модификаторами public или internal, или использовать значение по умолчанию «внутренний», поскольку пользователи, имеющие общедоступный или внутренний доступ к функции, могут не иметь соответствующего доступа к закрытому классу, используемому в типе возвращаемого значения функции.
Типы перечислений
Отдельные случаи перечисления автоматически получают тот же уровень доступа, что и перечисление, к которому они относятся. Нельзя указать другой уровень доступа для отдельных случаев перечисления.
В примере ниже перечисление CompassPoint имеет явный уровень доступа «общедоступный». Следовательно, случаи перечисления north, south, east и west также имеют уровень доступа «общедоступный»:
public enum CompassPoint {
case north
case south
case east
case west
} Необработанные значения и связанные значения
Типы, используемые для любых необработанных значений или связанных значений в определении перечисления, должны иметь уровень доступа, по крайней мере, такой же высокий, как и уровень доступа перечисления. Например, нельзя использовать закрытый тип в качестве типа необработанного значения перечисления с уровнем доступа «внутренний».
Вложенные типы
Уровень доступа вложенного типа такой же, как у содержащего типа, если содержащий тип не является общедоступным. Вложенные типы, определенные внутри общедоступного типа, имеют автоматический уровень доступа «внутренний». Если вы хотите, чтобы вложенный тип внутри общедоступного типа был общедоступен, необходимо явно объявить вложенный тип как «общедоступный».
Наследование
Вы можете наследоваться от любого класса, к которому можно получить доступ в текущем контексте доступа и который определен в том же модуле, что и подкласс. Вы также можете наследоваться от любого открытого класса, определенного в другом модуле. Подкласс не может иметь более высокий уровень доступа, чем его суперкласс — например, вы не можете написать общедоступный подкласс закрытого суперкласса.
Кроме того, для классов, определенных в том же модуле, вы можете переопределять любые члены класса (методы, свойства, инициализаторы или индексы), которые видны в определенном контексте доступа. Для классов, определенных в другом модуле, вы можете переопределять любые открытые члены класса.
Переопределение может сделать унаследованный член класса более доступным, чем его версия в суперклассе. В примере ниже класс A является общедоступным классом со скрытым в файле методом, называемым someMethod(). Класс B является подклассом A с пониженным уровнем доступа «внутренний». Тем не менее, класс B предоставляет переопределение someMethod() с уровнем доступа «внутренний», который выше, чем исходная реализация someMethod():
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {}
} Даже допустимо, чтобы член подкласса вызывал член суперкласса, имеющий более низкий уровень доступа, чем член подкласса, если вызов члена суперкласса происходит в пределах разрешенного контекста доступа (то есть в том же исходном файле, что и суперкласс, для вызова члена, закрытого в файле, или в том же модуле, что и суперкласс, для вызова внутреннего члена):
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {
super.someMethod()
}
} Поскольку суперкласс A и подкласс B определены в одном исходном файле, допустимо, что реализация B someMethod() вызывает super.someMethod().
Константы, переменные, свойства и индексы
Константа, переменная или свойство не могут быть более общедоступными, чем его тип. Например, недопустимо написать общедоступное свойство с закрытым типом. Аналогично, индекс не может быть более общедоступным, чем его тип индекса или тип возвращаемого значения.
Если константа, переменная, свойство или индекс используют закрытый тип, константа, переменная, свойство или индекс также должны быть помечены как private:
private var privateInstance = SomePrivateClass()
Геттеры и сеттеры
Геттеры и сеттеры для констант, переменных, свойств и индексов автоматически получают тот же уровень доступа, что и константа, переменная, свойство или индекс, к которому они относятся.
Вы можете присвоить сеттеру более низкий уровень доступа, чем соответствующему геттеру, чтобы ограничить область чтения-записи этой переменной, свойства или индекса. Вы присваиваете более низкий уровень доступа, написав fileprivate(set), private(set), internal(set) или package(set) перед var или subscript.
Примечание: Это правило применяется как к хранимым свойствам, так и к вычисляемым свойствам. Несмотря на то, что вы не пишете явного геттера и сеттера для хранимого свойства, Swift все равно создает неявный геттер и сеттер для вас, чтобы предоставить доступ к хранилищу хранимого свойства. Используйте
fileprivate(set),private(set),internal(set)иpackage(set), чтобы изменить уровень доступа этого синтезированного сеттера точно так же, как для явного сеттера в вычисляемом свойстве.
В примере ниже определена структура под названием TrackedString, которая отслеживает количество раз, когда строковое свойство изменяется:
struct TrackedString {
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits += 1
}
}
} Структура TrackedString определяет хранимое строковое свойство, называемое value, со значениями по умолчанию "" (пустая строка). Структура также определяет хранимое целочисленное свойство, называемое numberOfEdits, которое используется для отслеживания количества раз, когда value изменяется. Это отслеживание изменений реализовано с помощью наблюдателя didSet свойства value, который увеличивает numberOfEdits каждый раз, когда свойство value устанавливается в новое значение.
Структура TrackedString и свойство value не имеют явного модификатора уровня доступа, поэтому оба получают уровень доступа по умолчанию «внутренний». Однако уровень доступа для свойства numberOfEdits помечен модификатором private(set), чтобы указать, что геттер свойства по-прежнему имеет уровень доступа по умолчанию «внутренний», но свойство может быть установлено только из кода, который является частью структуры TrackedString. Это позволяет TrackedString изменять свойство numberOfEdits внутри, но представлять свойство как свойство только для чтения при использовании его за пределами определения структуры.
Если вы создадите экземпляр TrackedString и несколько раз измените его строковое значение, вы сможете увидеть, как значение свойства numberOfEdits обновляется, чтобы соответствовать количеству изменений:
var stringToEdit = TrackedString()
stringToEdit.value = "This string will be tracked."
stringToEdit.value += " This edit will increment numberOfEdits."
stringToEdit.value += " So will this one."
print("The number of edits is \(stringToEdit.numberOfEdits)")
// Prints "The number of edits is 3" Хотя вы можете получить доступ к текущему значению свойства numberOfEdits из другого исходного файла, вы не можете изменять свойство из другого исходного файла. Это ограничение защищает реализацию деталей функциональности отслеживания изменений TrackedString, сохраняя при этом удобный доступ к аспекту этой функциональности.
Обратите внимание, что вы можете присвоить явный уровень доступа как для геттера, так и для сеттера, если это необходимо. В примере ниже показана версия структуры TrackedString, в которой структура определена с явным уровнем доступа «общедоступный». Члены структуры (включая свойство numberOfEdits) по умолчанию имеют уровень доступа «внутренний». Вы можете сделать геттер свойства numberOfEdits структуры общедоступным, а его сеттер — закрытым, объединив модификаторы уровня доступа public и private(set):
public struct TrackedString {
public private(set) var numberOfEdits = 0
public var value: String = "" {
didSet {
numberOfEdits += 1
}
}
public init() {}
} Инициализаторы
Пользовательским инициализаторам можно назначить уровень доступа, меньший или равный типу, который они инициализируют. Единственное исключение — для обязательных инициализаторов (как определено в <doc:Initialization#Required-Initializers>). Обязательный инициализатор должен иметь тот же уровень доступа, что и класс, к которому он относится.
Как и параметры функций и методов, типы параметров инициализатора не могут быть более закрытыми, чем собственный уровень доступа инициализатора.
Инициализаторы по умолчанию
Как описано в <doc:Initialization#Default-Initializers>, Swift автоматически предоставляет инициализатор по умолчанию без аргументов для любой структуры или базового класса, который предоставляет значения по умолчанию для всех своих свойств и не предоставляет хотя бы один инициализатор.
Инициализатор по умолчанию имеет тот же уровень доступа, что и тип, который он инициализирует, за исключением случаев, когда этот тип определен как public. Для типа, определенного как public, инициализатор по умолчанию считается внутренним. Если вы хотите, чтобы общедоступный тип можно было инициализировать с инициализатором без аргументов, когда он используется в другом модуле, вы должны явно указать общедоступный инициализатор без аргументов в определении типа.
Инициализаторы по умолчанию для структур
Инициализатор по умолчанию для структуры считается закрытым, если любое из хранимых свойств структуры является закрытым. Аналогично, если какое-либо из хранимых свойств структуры является закрытым в пределах файла, инициализатор будет закрытым в пределах файла. В противном случае инициализатор имеет уровень доступа «внутренний».
Как и в случае с инициализатором по умолчанию выше, если вы хотите, чтобы общедоступная структура можно было инициализировать с помощью инициализатора по умолчанию, когда она используется в другом модуле, вы должны указать общедоступный инициализатор по умолчанию в определении типа.
Протоколы
Если вы хотите назначить явный уровень доступа к типу протокола, сделайте это в момент определения протокола. Это позволяет создавать протоколы, которые могут быть реализованы только в определенном контексте доступа.
Уровень доступа каждого требования в определении протокола автоматически устанавливается таким же, как и уровень доступа протокола. Нельзя установить требование протокола на другой уровень доступа, отличный от уровня доступа протокола, который он поддерживает. Это гарантирует, что все требования протокола будут видны в любом типе, который соответствует протоколу.
Примечание: Если вы определяете общедоступный протокол, требования протокола требуют уровня доступа «общедоступный» при их реализации. Это поведение отличается от других типов, где определение общедоступного типа подразумевает уровень доступа «внутренний» для членов типа.
Наследование протоколов
Если вы определяете новый протокол, который наследуется от существующего протокола, новый протокол может иметь не более высокий уровень доступа, чем протокол, от которого он наследуется. Например, вы не можете написать общедоступный протокол, который наследуется от внутреннего протокола.
Соответствие протоколу
Тип может соответствовать протоколу с более низким уровнем доступа, чем сам тип. Например, вы можете определить общедоступный тип, который может использоваться в других модулях, но его соответствие внутреннему протоколу может использоваться только внутри модуля, определяющего внутренний протокол.
END_OF_DOCUMENT_MARKERКонтекст, в котором тип соответствует определённому протоколу, является минимальным из уровня доступа типа и уровня доступа протокола. Например, если тип является общедоступным, но протокол, которому он соответствует, является внутренним, соответствие типа этому протоколу также будет внутренним.
При написании или расширении типа для соответствия протоколу необходимо убедиться, что реализация типа каждого требования протокола имеет как минимум такой же уровень доступа, как и соответствие типа этому протоколу. Например, если общедоступный тип соответствует внутреннему протоколу, реализация типа каждого требования протокола должна быть как минимум внутренней.
Примечание: в Swift, как и в Objective-C, соответствие протоколам является глобальным — тип не может соответствовать протоколу двумя различными способами в пределах одной программы.
Расширения
Вы можете расширить класс, структуру или перечисление в любом контексте доступа, в котором доступен класс, структура или перечисление. Любые члены типа, добавленные в расширение, имеют тот же уровень доступа по умолчанию, что и члены типа, объявленные в исходном типе, расширяемом. Если вы расширяете общедоступный или внутренний тип, любые новые члены типа имеют уровень доступа по умолчанию — внутренний. Если вы расширяете тип с уровнем доступа «внутри файла», любые новые члены типа имеют уровень доступа по умолчанию — «внутри файла». Если вы расширяете тип с уровнем доступа «приватный», любые новые члены типа имеют уровень доступа по умолчанию — «приватный».
В качестве альтернативы вы можете пометить расширение явным модификатором уровня доступа (например, private), чтобы установить новый уровень доступа по умолчанию для всех членов, определённых в расширении. Этот новый уровень доступа по умолчанию по-прежнему может быть переопределён внутри расширения для отдельных членов типа.
Вы не можете указать явный модификатор уровня доступа для расширения, если вы используете это расширение для добавления соответствия протоколу. Вместо этого используется собственный уровень доступа протокола для предоставления уровня доступа по умолчанию для каждой реализации требования протокола внутри расширения.
Приватные члены в расширениях
Расширения, которые находятся в том же файле, что и класс, структура или перечисление, которые они расширяют, ведут себя так, как будто код в расширении был написан как часть объявления исходного типа. В результате вы можете:
- Объявить приватный член в исходном объявлении и получить доступ к этому члену из расширений в том же файле.
- Объявить приватный член в одном расширении и получить доступ к этому члену из другого расширения в том же файле.
- Объявить приватный член в расширении и получить доступ к этому члену из исходного объявления в том же файле.
Это поведение означает, что вы можете использовать расширения таким же образом для организации кода, независимо от того, имеют ли ваши типы приватные элементы. Например, учитывая следующий простой протокол:
protocol SomeProtocol {
func doSomething()
} Вы можете использовать расширение для добавления соответствия протоколу, например так:
struct SomeStruct {
private var privateVariable = 12
}
extension SomeStruct: SomeProtocol {
func doSomething() {
print(privateVariable)
}
} Обобщения
Уровень доступа к обобщённому типу или обобщённой функции является минимальным из уровня доступа к обобщённому типу или функции и уровня доступа к любым ограничениям типа на его параметрах типа.
Псевдонимы типов
Любые определённые вами псевдонимы типов обрабатываются как отдельные типы для целей управления доступом. Псевдоним типа может иметь уровень доступа меньше или равен уровню доступа типа, к которому он относится. Например, приватный псевдоним типа может ссылаться на приватный, «внутри файла», внутренний, общедоступный или открытый тип, но общедоступный псевдоним типа не может ссылаться на внутренний, «внутри файла» или приватный тип.
Примечание: это правило также применяется к псевдонимам типов для связанных типов, используемых для удовлетворения соответствия протоколам.
This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception