In addition to the Apple guidelines, we generally prefer to use struct for:
- Value types like the Networking Models
- Stateless helpers
But consider using class instead if:
- You need to manage mutable states. Especially if there are more than a few
mutatingfunctions, thestructbecomes harder to reason about. - You have to set a
structproperty declaration asvarbecause it has amutatingfunction. In this case, a constant (let)classproperty may be easier to reason about.
When using classes, these should be marked as final by default so their behavior cannot be altered by subclassing and/or overriding. There's a few reasons for that:
- It favors composition over inheritance
- The class could be missused or abused when subclassed or overriden, which could be problematic if the class is doing anything important. By making it
finalwe disallow this at compiler time, and enforce that the class has to be used as it was written. - Marking a class as
finaltells the Swift compiler that the class methods should be called directly rather than looking them up in a method table (static vs dynamic dispatch), which reduces function call overhead and increases performance - If inheritance is necessary later on, it can always be allowed, but the
finalmodifier will create a reminder of its necessity and refactoring