# Classes, Inheritance and Initialisation — Swift

Source: https://www.skillbyai.com/en/swift/t-classes

> Use classes with initialisers, inheritance, deinit and identity.

## Reference types

**Classes** are **reference types**: variables hold references to a shared instance, so changes through one reference are visible through all others, and `===` checks whether two references point to the same object. Classes support **inheritance** (a single superclass), **overriding** with the `override` keyword, `final` to prevent subclassing, and **`deinit`** for cleanup when the instance is freed. Unlike structs, classes get no memberwise initialiser. Swift's **initialisation rules** guarantee every stored property has a value before use: **designated initialisers** fully initialise a class (calling `super.init` after setting their own properties), and **convenience initialisers** delegate to a designated one. Initialisers can be **failable** (`init?`) to return nil for invalid input. Mark classes `final` unless you design them for subclassing; it also lets the compiler optimise method calls. Classes are needed for shared mutable state, identity (such as a cache or a coordinator object), inheritance-based frameworks such as UIKit, and Objective-C interoperability.

## A class with inheritance, a failable init and deinit

References share one instance; identity is checked with ===.

```swift
class Account {
    let owner: String
    private(set) var balance: Double

    init?(owner: String, opening: Double) {      // failable initialiser
        guard opening >= 0 else { return nil }
        self.owner = owner
        self.balance = opening
    }

    func deposit(_ amount: Double) { balance += amount }
    func describe() -> String { "\(owner): \(balance)" }

    deinit { print("Account for \(owner) released") }
}

final class SavingsAccount: Account {
    let rate: Double

    init?(owner: String, opening: Double, rate: Double) {
        self.rate = rate                       // own properties first
        super.init(owner: owner, opening: opening)
    }

    override func describe() -> String { super.describe() + " at \(rate)%" }
}

if let a = Account(owner: "Asha", opening: 1000) {
    let b = a                                  // same instance
    b.deposit(500)
    print(a.balance)                           // 1500.0
    print(a === b)                             // true: identical reference
}
```

## private(set) keeps state honest

`private(set) var balance` lets anyone read the balance but only the class change it, so all changes go through methods that enforce your rules.

**Quiz:** What does the === operator check for class instances?

- [ ] Equal property values
- [ ] Whether two classes share a superclass
- [x] Whether two references point to the same instance
- [ ] Whether instances are Equatable

*Answer:* Whether two references point to the same instance. === is identity comparison; == uses Equatable value equality.
