3
votes

Using protocol extensions, I can make any object conform to my own protocol as long as I provide an implementation for that. E.g. let's assume I create a protocol:

protocol Printable {
    // ... whatever ...
}

Now I can make Strings and Ints printable like that:

extension String: Printable {
    // ... whatever is required to satisfy protocol ...
}

extension Int: Printable {
    // ... whatever is required to satisfy protocol ...
}

This is a very cool way of programming as I now can feed Strings and Ints into whatever function I have that can deal with Printables.

Now if I have an Array of Printables, the whole Array is printable, so I try to do that:

extension Array<Printable>: Printable {
    // ... whatever is required to satisfy protocol ...
}

But the compiler doesn't like it.

Constraint extension must be declared on then unspecialized generic type "Array" with constraints specified by a "where" clause.

For normal extensions that isn't a problem. I can just do this:

extension Array where Element: Printable {

}

This works as expected. Whatever I put into the extension above only applies to Arrays of Printable elements. But this will not make an Array of Printable elements conform to the Printable protocol itself. This is just a normal extension, not a so called "protocol extension".

1
You can't have conditional conformance.R Menke
@RMenke Why not writing that as a reply? And are you sure about that? Because as far as I understood it Array<String> and Array<Int> are actually totally distinct types to to the Swift Type System, so in theory distinct types can have distinct conformance - after all the can have distinct extensions as well. If that is not possible, I should seriously file a request for Swift 3.0 as that would be an important feature in many situations.Mecki
I did not write it as a reply, because this is actually a duplicate question ;). I am sure about it. Array<String> and Array<Int> are of the same type. Just with a different Type for typealias Element. Conditional conformance has also been requested since Swift 2.0 came out but it hasn't happened yet.R Menke
@RMenke Even if it was a dupe, you won't get punished for answering the question and you also don't lose any reputation when it is closed as dupe :) I will give you an upvote, if you write a real answer ;) If generics are not different types, how can they have different extensions? And how can the compiler know that hey have because it does know already at compile time if a function is available or not, which will only depend the type of Element. So the compiler must have some special logic here and with exactly the same logic, it could also test conformance in theory.Mecki
I completely agree with you on that last part and a lot of times I start refactoring something to a more protocol oriented way and hit this wall, I know this wall, it has my face imprinted in it by now. I'm just happy at this point that we have extensions with constraints.R Menke

1 Answers

5
votes

You can do this in Swift 4.1

extension Array: Printable where Element: Printable {
    // ...
}