Generics allow defining flexible and reusable functions and types. A key feature of Swift is maintaining type safety: the compiler checks the use of specific types at compile time. Generic types can be constrained using where clauses, protocol inheritance, and their combinations.
Code example:
func swapValues<T>(_ a: inout T, _ b: inout T) { let temp = a a = b b = temp } protocol Drawable { func draw() } func drawAll<T: Drawable>(_ items: [T]) { for item in items { item.draw() } } // Constraint by protocol and where clause func compareValues<T: Equatable>(_ a: T, _ b: T) -> Bool { return a == b }
Can generic functions act as overloaded functions? How does the compiler choose the right implementation?
Answer: Yes, generic functions can be overloaded with regular and other generic functions. The compiler tries to select the most specific implementation. Example:
func printValue(_ value: Int) { print("Int: \(value)") } func printValue<T>(_ value: T) { print("Generic: \(value)") } printValue(5) // Int: 5 printValue("Swift") // Generic: Swift
Story
The team wrote a generic extension for an array to find the index while forgetting to constrain the type through Equatable. This resulted in a compilation error when trying to apply the extension to an array with non-Equatable elements.
Story
In the project, an attempt was made to implement a cache for generic objects without type constraints. As a result, when attempting to downcast at runtime, crashes occurred — real safe usage could have been achieved through protocols with associated types and constraints.
Story
Developers implemented a generic class, but when inheriting and overriding, they forgot the necessity to specify the complete generic parameter of the subclass. This caused the code not to compile and required a complete redesign of the type hierarchy.