Menu
Coddy logo textTech

Контроль доступа

Часть раздела Объектно-ориентированное программирование путешествия по Swift на Coddy. Урок 17 из 57.

Инкапсуляция означает, что тип управляет тем, как можно использовать его данные. Управление доступом определяет, кто может видеть свойство или метод. Пометка члена как private скрывает его от всего кода за пределами типа (и его расширений в том же файле):

struct Account {
    private var balance = 0

    mutating func deposit(_ amount: Int) {
        balance += amount
    }
}

var a = Account()
a.deposit(50)
// a.balance = 1_000_000   // ошибка: 'balance' недоступен из-за уровня защиты 'private'

Внешний код может использовать только то, что предоставляет тип. Тип может проверять каждое изменение, поэтому его данные никогда не окажутся в состоянии, которое тип не допускает:

struct Account {
    private var balance = 0

    mutating func deposit(_ amount: Int) {
        if amount > 0 { balance += amount }
    }

    func report() -> String {
        "balance: \(balance)"
    }
}

var a = Account()
a.deposit(50)
a.deposit(-999)
print(a.report())

Вывод:

balance: 50

В Swift есть пять уровней доступа. Без ключевого слова член имеет уровень internal: он виден везде в том же модуле (вашем приложении или пакете). Уровни от наиболее открытого до наиболее ограниченного:

open        // другие модули могут использовать и наследовать его (только классы)
public      // другие модули могут использовать его
internal    // по умолчанию: весь модуль
fileprivate // только этот исходный файл
private     // этот тип (и его расширения в файле)

Приватные вспомогательные методы позволяют сделать публичный интерфейс небольшим: вызывающие видят, что делает тип, а не то, как он это делает.

struct Password {
    private let text: String

    init(_ text: String) { self.text = text }

    var isStrong: Bool {
        hasDigit() && text.count >= 8
    }

    private func hasDigit() -> Bool {
        text.contains { $0.isNumber }
    }
}

print(Password("secret123").isStrong)
print(Password("short1").isStrong)

Вывод:

true
false
challenge icon

Задание

Легко

Завершите структуру Locker. Её code и items имеют модификатор доступа private. store(_:code:) добавляет элемент только при совпадении кода и возвращает, удалось ли это; items(code:) возвращает сохранённые элементы, объединённые с помощью , (или empty), если код совпадает, и wrong code в противном случае.

Предоставленный код считывает код замка, а затем команды put <code> <item> или open <code>. Для каждой команды put он выводит stored или denied, а для каждой команды open — результат.

Ваш код должен находиться в Locker.swift. В main.swift содержится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

// Предоставленный код ввода/вывода: оставьте его как есть
var input: [String] = []
while let line = readLine() { input.append(line) }
var locker = Locker(code: input[0])
for cmd in input.dropFirst() {
    let p = cmd.split(separator: " ").map(String.init)
    if p[0] == "put" {
        print(locker.store(p[2], code: p[1]) ? "stored" : "denied")
    } else {
        print(locker.items(code: p[1]))
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Swift