Let's say I'm making a fist person shooter, where players are divided randomly into six teams, and every team keeps track of their kills and deaths.
struct TeamRef: CustomStringConvertible {
static let numberOfTeams = 6
private static var kills: [Int] = .init(repeating: 0, count: numberOfTeams)
private static var deaths: [Int] = .init(repeating: 0, count: numberOfTeams)
private var teamIdx: Array<Int>.Index = Int.random(in: 0..<numberOfTeams)
var kills: Int {
get {
Self.kills[teamIdx]
}
nonmutating set {
Self.kills[teamIdx] = newValue
}
}
var deaths: Int {
get {
Self.deaths[teamIdx]
}
nonmutating set {
Self.deaths[teamIdx] = newValue
}
}
var description: String {
"kd: \(kills)/\(deaths)"
}
}
let team = TeamRef()
team.kills += 1
let teamCopy = team
teamCopy.deaths += 10
print(team) // kd: 1/10
This type has reference semantics, all the properties (stored and computed) are Int
, which is specifically mentioned in the pitch as a type that would be ValueSemantic
.
Why didn't I use a class for the Team
?
- Why not? It's correct swift today.
- If I want to do something with all the kills, it's better for cache for them to be in the same place in memory
- I can change the stored property type to something like
UInt8
and get 8 times smaller size compared to a class - it eliminates ARC overhead