Menu
Coddy logo textTech

Read-Only From Outside

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

Often outside code should read a property but not change it. private(set) keeps the getter at the normal level and makes only the setter private:

struct Counter {
    private(set) var count = 0

    mutating func increment() {
        count += 1
    }
}

var c = Counter()
c.increment()
print(c.count)
// c.count = 99   // error: setter is private

Output:

1

This fits values that must only change through a rule, such as a score that only goes up through valid actions:

class Player {
    let name: String
    private(set) var score = 0
    private(set) var history: [Int] = []

    init(name: String) { self.name = name }

    func award(_ points: Int) {
        guard points > 0 else { return }
        score += points
        history.append(points)
    }
}

let p = Player(name: "Ada")
p.award(10)
p.award(-5)
p.award(3)
print(p.score)
print(p.history)

Output:

13
[10, 3]

A let property is read-only for everyone once the instance exists, including the type's own methods. private(set) var stays changeable inside the type. Choose let for values that never change after creation:

class Order {
    let id: Int                 // never changes
    private(set) var status = "new"   // changes, but only inside Order
    init(id: Int) { self.id = id }
    func ship() { status = "shipped" }
}

A read-only computed property is another way to expose information without allowing changes, because it has no setter at all:

struct Cart {
    private var prices: [Int] = []
    var total: Int { prices.reduce(0, +) }
    var count: Int { prices.count }

    mutating func add(_ price: Int) { prices.append(price) }
}

var cart = Cart()
cart.add(4)
cart.add(6)
print("\(cart.count) items, total \(cart.total)")

Output:

2 items, total 10
challenge icon

Challenge

Easy

Complete the class Elevator. floor and trips can be read from outside but only changed by the class (private(set)). goTo(_:) moves between floor 0 and topFloor: a valid move to a different floor updates floor, adds 1 to trips and returns true; an invalid or same-floor move returns false.

The supplied code reads the top floor and then target floors. It prints floor 3 after a move or stay 3 when the move was refused, and finally trips: with the count.

Your code goes in Elevator.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) }
let lift = Elevator(topFloor: Int(input[0])!)
for line in input.dropFirst() {
    let moved = lift.goTo(Int(line)!)
    print("\(moved ? "floor" : "stay") \(lift.floor)")
}
print("trips: \(lift.trips)")
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