Properties and Methods
Stored and computed properties, mutating methods, and how initializers set up an instance.
読了時間 2 分
Structs and classes both organize data (properties) and behavior (methods) together. Swift distinguishes a few flavors of each that are worth knowing by name.
Stored properties and initializers
struct Rectangle {
var width: Double
var height: Double
}
let box = Rectangle(width: 10, height: 5)Swift automatically generates a memberwise initializer for structs — Rectangle(width:height:) above — based on its stored properties, so you often don't need to write an initializer yourself. Classes don't get this for free; they require an explicit init:
class Rectangle {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
}self refers to the instance being initialized — needed here because the parameter names (width) shadow the property names (self.width).
Computed properties
A computed property doesn't store a value at all — it calculates one every time it's accessed, using a get block (and optionally a set):
struct Rectangle {
var width: Double
var height: Double
var area: Double {
return width * height
}
}
let box = Rectangle(width: 10, height: 5)
print(box.area) // 50 — recalculated fresh each time, never staleBecause area is always derived from width and height, storing it separately would risk it going out of sync if either changes. A computed property guarantees that can never happen.
Methods, and mutating methods on structs
struct Rectangle {
var width: Double
var height: Double
func area() -> Double {
return width * height
}
mutating func scale(by factor: Double) {
width *= factor
height *= factor
}
}
var box = Rectangle(width: 10, height: 5)
box.scale(by: 2)
print(box.width) // 20Because a struct is a value type, a method that changes its own properties must be explicitly marked mutating — without that keyword, the compiler won't let the method reassign width or height, since ordinary methods treat the instance as read-only. Classes never need mutating, since changing a class instance's properties doesn't require replacing the whole value the way a struct's does.
Property observers
didSet and willSet run code automatically whenever a stored property changes — useful for reacting to a change without the caller doing anything extra:
struct Account {
var balance: Double {
didSet {
print("Balance changed from \(oldValue) to \(balance)")
}
}
}
var account = Account(balance: 100)
account.balance = 150
// prints: "Balance changed from 100.0 to 150.0"oldValue is automatically available inside didSet, giving you the previous value without needing to store it yourself beforehand.