One of the key benefits of generic code is that it can enable us to reuse types, protocols, logic, and data across many different use cases. Not only can that lead to less code duplication, but it can also have architectural benefits, since generic code tends to become better encapsulated and less tied to specific features by default.
However, if we’re not careful, generics can also greatly increase the overall complexity of our code, and can often lead to problems like over-generalization and premature optimization.
So, on this Discover page, we’ll not only take a look at how to actually write generic Swift code, but also when and how generics can be pragmatically deployed to solve various kinds of problems, while also avoiding some of those common traps in the process.
Since so many of the standard library’s built-in types are generic (including data structures like
Dictionary), it’s very common to want to add new, slightly more domain-specific APIs to them within our code bases. For example, using type-constrained extensions we can specialize types and protocols to fit our needs, and by using techniques like protocol specialization, we can use both composition and inheritance in really useful ways.
These articles cover those kinds of techniques, and how we can use them with both built-in and custom types and protocols:
Now that we’ve covered both the basics, as well as more advanced generic programming techniques, let’s dive into a few examples on how generics can be used to build robust, reusable code that leverages the Swift type system to validate our logic:
At some point, most developers who write generic Swift code are very likely to encounter the topic of type erasure — that is, when we need to remove some of the generic type information from one of our types or protocols in order to be able to reference it directly.
Here are a few articles that cover various ways to perform type erasure, as well as when and why those techniques might be needed:
Finally, let’s wrap things up by taking a look at a few ways to make generic code read a bit better, as well as how we can utilize language features like opaque return types and type aliases to make our generic types and protocols easier to work with: