Reputation: 83
In the Swift documentation, I came across a section which was saying that I can write type constraints like a method or a protocol. However, what I didn't understand were the benefits of writing this way. Why don't simply pass the class (or protocol) itself?
Documentation: https://docs.swift.org/swift-book/LanguageGuide/Generics.html
Let me explain with an example.
import Foundation
class A {
init(val: String) {
self.val = val
}
let val: String
}
func someFunction<T: A>(someT: T) {
print(someT.val)
}
func someFunction2(someT: A) {
print(someT.val)
}
// method 1
someFunction(someT: A(val: "asdasd"))
// method 2
someFunction2(someT: A(val: "asdasd"))
In the snippet below, what is the difference between method 1 and method 2?
Upvotes: 1
Views: 77
Reputation: 54775
In your overly simplified example, there's not much difference.
However, as soon as your type constraints become more complex, the only way to achieve the desired interface is via generics.
A great example if when you want a function to take an input argument whose type is a protocol with an associated type, such as SwiftUI's View
.
If you tried to use View
as the input argument type, you'd get a compile time error
func modifyView(_ view: View) {
}
Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
However, as soon as you make view
generic with a type constraint on View
, the code compiles.
func modifyView<V: View>(_ view: V) {
}
You don't have to look at custom functions, the standard library is full of generic functions as well. JSONDecoder.decode
showcases another common use case for generics, when you want your function to return a specific type based on some input arguments. This enables the developer to only write the function 1x, but make it work on lots of different types, while keeping type safety.
func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T
Upvotes: 1