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
.