Swift
Beginner
1 min read
Generics and Protocol Constraints
Example
// Protocol with associated type
protocol Repository {
associatedtype Entity
func findAll() -> [Entity]
func findById(_ id: Int) -> Entity?
func save(_ entity: Entity)
}
struct UserRepository: Repository {
private var users: [Int: User] = [:]
func findAll() -> [User] { Array(users.values) }
func findById(_ id: Int) -> User? { users[id] }
mutating func save(_ user: User) { users[user.id] = user }
}
// some (opaque return type) - concrete type hidden but fixed
func makeRepository() -> some Repository {
return UserRepository()
}
// Generic function constrained to protocol
func printAll<R: Repository>(_ repo: R) where R.Entity: CustomStringConvertible {
repo.findAll().forEach { print($0) }
}
// Primary associated type (Swift 5.7+)
protocol Collection<Element> { }
// any for type-erased storage
var repos: [any Repository] = []