Какие уровни доступа существуют в Swift?

Ответ

Swift предоставляет пять уровней доступа, от наиболее открытого к наиболее ограниченному:

1. open - Наиболее открытый доступ

open class NetworkManager {
    open func fetchData() { /* ... */ }
}
// Можно: наследовать, переопределять, использовать из других модулей

2. public - Открытый доступ

public struct APIResponse {
    public var data: Data
    internal var metadata: Metadata // Недоступно извне
}
// Можно: использовать из других модулей
// Нельзя: наследовать/переопределять классы из других модулей

3. internal - Доступ по умолчанию

internal class DataProcessor {
    func process() { /* ... */ } // По умолчанию internal
}
// Доступно только внутри модуля (framework или app)

4. fileprivate - Доступ в пределах файла

fileprivate class FileHelper {
    static func readFile() { /* ... */ }
}
// Доступно только в этом .swift файле

5. private - Наиболее ограниченный доступ

class BankAccount {
    private var balance: Decimal = 0

    private func calculateInterest() { /* ... */ }
}
// Доступно только в пределах объявляющей области (класса, структуры)

Ключевые правила:

  • Уровень доступа сущности не может быть более открытым, чем уровень доступа её типа
  • open применим только к классам и членам классов
  • private(set) позволяет публичное чтение, но приватную запись:
    public struct User {
    public private(set) var id: UUID // Чтение публично, запись приватно
    }

Области видимости в порядке убывания: open > public > internal > fileprivate > private

Ответ 18+ 🔞

А, ну это про уровни доступа в Swift, да? Слушай, тут такая хуйня интересная, как в армии звания, только для кода. Пять уровней, от генерала до рядового в сортире.

1. open — это как генерал, всем всё можно

open class NetworkManager {
    open func fetchData() { /* ... */ }
}

Этот такой: «Наследуй меня, переопределяй, делай что хочешь, я из другого модуля, но я не боюсь!». Самый распиздяйский уровень.

2. public — уже майор, тоже важный, но строже

public struct APIResponse {
    public var data: Data
    internal var metadata: Metadata // А это уже секретик, не покажем
}

Снаружи модуля его видно, пользоваться можно, но вот наследовать или переопределять — хуй тебе, а не переопределение. Только смотреть.

3. internal — сержант, дефолтный мужик

internal class DataProcessor {
    func process() { /* ... */ } // И так понятно, что internal
}

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

4. fileprivate — ефрейтор в своём взводе-файле

fileprivate class FileHelper {
    static func readFile() { /* ... */ }
}

Вот этот чувак доступен только в пределах одного .swift файла. Соседний файл — уже заграница, нихуя не узнает про этого ефрейтора. Удобно для внутренних делишек, чтобы не светить.

5. private — рядовой в своём туалете

class BankAccount {
    private var balance: Decimal = 0

    private func calculateInterest() { /* ... */ }
}

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

Важные приколы, чтобы не обосраться:

  • Нельзя сделать сущность публичнее, чем её тип. Не выйдет public var secret: PrivateType — компилятор наорет «чё за хуйня?».
  • open — только для классов и их членов. Структуре или енуму он нахуй не сдался.
  • Есть такая хитрая хуйня — private(set). Читать можно всем, а писать — только своим.
    public struct User {
    public private(set) var id: UUID // Смотрите, какой красивый ID, а тронуть — руки отобью
    }

Итог, короче, по убыванию крутости: open (генерал) > public (майор) > internal (сержант) > fileprivate (ефрейтор) > private (рядовой в душe).

Выбирай с умом, а то потом придётся рефакторить, а это пиздец как неохота.