It's easier to explain the problem on an example. For instance, consider this simple generic class:
final class GenericClass<T> {
private let parameter: T
init(parameter: T) {
self.parameter = parameter
}
}
I want to add an empty init in an extension, when T is any Array (or even Collection, but it's not crucial for my case). I want something like this, but it doesn't compile:
// Reference to generic type 'Array' requires arguments in <...>
extension GenericClass where T: Array {
convenience init() {
// Cannot convert value of type '[Any]' to expected argument type 'T'
self.init(parameter: [])
}
}
How can I add a generic parameter to the Array? This syntax doesn't work:
extension GenericClass<U> where T: Array<U> { // Cannot find type 'U' in scope
convenience init() {
self.init(parameter: [U]()) // Cannot call value of non-function type '[Any]'
}
}
(T == Array<U> doesn't work either.)
Is there any way to achieve what I described? I really would like to avoid declaring separate extensions for every element type I need (of course the code below works perfectly fine):
extension GenericClass where T == [Int] {
convenience init() {
self.init(parameter: [])
}
}
If you specifically need Array, you can add the extra type parameter U to the init. instead of extension GenericClass<U>:
extension GenericClass {
convenience init<U>() where T == [U] {
self.init(parameter: [])
}
}
If all the init needs is to be able to convert [] to T. T can just be something that's ExpressibleByArrayLiteral.
extension GenericClass where T: ExpressibleByArrayLiteral {
convenience init() {
self.init(parameter: [])
}
}
If by [] you specifically mean "an empty collection", then you should require T to be RangeReplaceableCollection. This protocol provides an init that creates an empty collection.
extension GenericClass where T: RangeReplaceableCollection {
convenience init() {
self.init(parameter: T())
}
}
It is not the case that ExpressibleByArrayLiteral implies that the type is a collection. OptionSet for example, is not a Collection, but it is ExpressibleByArrayLiteral.