Initialization and valid starting state
Initialization and valid starting state
A student record should not begin with an impossible score. An initializer prepares a new instance and establishes the required properties. A failable initializer, written init?, can decline to construct an instance when input violates its contract.
What you’ll learn
- Reject an invalid initial value with a failable initializer.
- Explain why later mutation also needs an invariant policy.
Initialization and valid starting state in the example
Validate input
A student record should not begin with an impossible score.
Validate inputInitialize stored value
Self names the instance being initialized, distinguishing its property from a same-named parameter.
Initialize stored valueOr return nil
The first initializer succeeds and stores 80.
Or return nil
How initialization and valid starting state works
Self names the instance being initialized, distinguishing its property from a same-named parameter. Stored properties must reach valid initial values under Swift’s initialization rules. A class’s designated and convenience initializers have delegation rules, especially when inheritance is involved.
Work through initialization and valid starting state
Save this complete program as main.swift and run it with the Swift toolchain. No separate input file is needed.
Swift · complete program
struct Mark {
let value: Int
init?(_ value: Int) {
guard (0...100).contains(value) else { return nil }
self.value = value
}
}
print(Mark(80)?.value ?? -1)
print(Mark(120) == nil)Expected output
80
trueFollow the execution
The first initializer succeeds and stores 80. The second returns nil because 120 is outside the accepted range. Optional chaining reads a value only from the successfully created instance.
Try this program in the Swift compiler. Paste the complete source above.
Practice: Initialization and valid starting state
Your task: What should Mark(-5) return under this contract?
Swift · complete program
struct Mark {
let value: Int
init?(_ value: Int) {
guard (0...100).contains(value) else { return nil }
self.value = value
}
}
print(Mark(80)?.value ?? -1)
print(Mark(120) == nil)Worked answer
It returns nil because the allowed closed range begins at zero. The caller must handle failure rather than receiving a partially valid mark.
Protect validity after construction too
A valid initial value does not guarantee later mutations stay valid. Keep sensitive storage immutable or route updates through validated methods. Deinitialization concerns class lifetime and resource cleanup, which differs from constructing a valid starting value.
Check your decision
Protect validity after construction too
It returns nil because the allowed closed range begins at zero. The caller must handle failure rather than receiving a partially valid mark. A valid initial value does not guarantee later mutations stay valid.
Further reading: official Swift language guide.
Reaching the recap and completing the quizzes are separate milestones.