I have a generic class that I want to be able to use with a default type. Right now I can initialize it with any type, but I have to be explicit.
//Initialize with a type MyManager<MyCustomerObject>() // Initialize with NSObject (what I want to be my default type) MyManager<NSObject>() // This doesn't work, but I want this kind of functionality class MyManager<T = NSObject> {} // So I can create my manager like so and it inserts the default type as NSObject MyManager() //Or MyManager<>()
Is this possible in Swift?
The placeholder type T is used in the function declaration. It tells Swift that this function can find any item in any array, as long as the foundItem and items in the array are of the same type. This makes sense — you want to look for a T value in an array of T values.
Generics and Any are often used for similar purposes, yet they behave very differently. In languages without generics, you typically use a combination of Any and runtime programming, whereas generics are statically checked at compile time.
Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.
There's no support for default generic arguments, but you can fake it by defining the default init()
on a type-constrained extension, in which case the compiler will be smart enough to use that type. E.g.:
class MyManager<T> { let instance: T init(instance: T) { self.instance = instance } } extension MyManager where T == NSObject { convenience init() { self.init(instance: NSObject()) } }
And now you can initialize the type with no argument and it will default to MyManager<NSObject>
:
let mm1 = MyManager(instance: "Foo") // MyManager<String> let mm2 = MyManager(instance: 1) // MyManager<Int> let mm3 = MyManager() // MyManager<NSObject>
SwiftUI uses this technique quite a lot.
No, this currently isn't possible – although it is a part of the Generics Manifesto, so might be something that the Swift team will consider for a future version of the language.
Default generic arguments
Generic parameters could be given the ability to provide default arguments, which would be used in cases where the type argument is not specified and type inference could not determine the type argument. For example:
public final class Promise<Value, Reason=Error> { ... } func getRandomPromise() -> Promise<Int, Error> { ... } var p1: Promise<Int> = ... var p2: Promise<Int, Error> = p1 // okay: p1 and p2 have the same type Promise<Int, Error> var p3: Promise = getRandomPromise() // p3 has type Promise<Int, Error> due to type inference
In the meantime however, a somewhat unsatisfactory compromise would be the use of a typealias
:
class MyManager<T> {} typealias MyManagerDefault = MyManager<NSObject> let defaultManager = MyManagerDefault()
Not nearly as slick as just being able to say MyManager()
, but it does show up next to MyManager
in auto-complete, which is pretty handy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With