Burak
Burak

Reputation: 83

What is the difference between passing classes as generic types or types?

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

Answers (1)

David Pasztor
David Pasztor

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

Related Questions