Menu
Coddy logo textTech

Access Control

Part of the Object Oriented Programming section of Coddy's Swift journey. Lesson 17 of 57.

Encapsulation means a type controls how its data can be used. Access control decides who can see a property or method. Marking a member private hides it from all code outside the type (and its extensions in the same file):

struct Account {
    private var balance = 0

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

var a = Account()
a.deposit(50)
// a.balance = 1_000_000   // error: 'balance' is inaccessible due to 'private' protection level

Outside code can then only use what the type offers. The type can check every change, so its data never ends up in a state the type does not allow:

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())

Output:

balance: 50

Swift has five access levels. Without a keyword a member is internal: visible everywhere in the same module (your app or package). The levels from most open to most restricted:

open        // other modules can use and subclass it (classes only)
public      // other modules can use it
internal    // default: the whole module
fileprivate // this source file only
private     // this type (and its extensions in the file)

Private helper methods keep the public surface small: callers see what the type does, not how it does it.

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)

Output:

true
false
challenge icon

Challenge

Easy

Complete the struct Locker. Its code and items are private. store(_:code:) adds an item only when the code matches and returns whether it did; items(code:) returns the stored items joined with , (or empty) when the code matches, and wrong code otherwise.

The supplied code reads the locker's code and then commands put <code> <item> or open <code>. It prints stored or denied for each put, and the result for each open.

Your code goes in Locker.swift. main.swift holds the supplied input/output code and cannot be edited.

Try it yourself

// Supplied input/output code: keep it as it is
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 iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Swift playground