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 privateOutput:
1This 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 10Challenge
EasyComplete 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)")
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesMethods and selfInitializersClasses Are ReferencesRecap - Library Card4Encapsulation
Access ControlRead-Only From OutsideGuarding StateFailable InitializersRecap - Bank Account7Polymorphism and Generics
PolymorphismType CastingGeneric FunctionsGeneric TypesRecap - Shape Calculator5Inheritance
SubclassesOverriding MethodsInitializers and superfinal and HierarchiesRecap - Employee Hierarchy11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Swift playground