Lets say I have two protocols:
protocol TheirPcol {}
protocol MyPcol {
func extraFunc()
}
What I want to do is to create a protocol extension for 'TheirPcol' which lets extraFunc()
work on anything which conforms to 'TheirPcol'. So something like this:
extension TheirPcol : MyPcol { // Error 'Extension of protocol 'TheirPcol' cannot have an inheritance clause.
func extraFunc() { /* do magic */}
}
struct TheirStruct:TheirPcol {}
let inst = TheirStruct()
inst.extraFunc()
The kicker in this is that 'TheirPcol', 'TheirStruct' are all handled by an external API which I do not control. So I'm passed the instance 'inst'.
Can this be done? Or am I going to have to do something like this:
struct TheirStruct:TheirPcol {}
let inst = TheirStruct() as! MyPcol
inst.extraFunc()
It seems there are two use-cases of why you may want to do what you are doing. In the first use-case, Swift will allow you to do what you want, but not very cleanly in the second use-case. I'm guessing you fall into the second category, but I'll go through both.
Extending the functionality of
TheirPcol
One reason why you might want to do this is simply to give extra functionality to
TheirPcol
. Just like the compiler error says, you cannot extend Swift protocols to conform to other protocols. However, you can simply extendTheirPcol
.Here, you are giving all objects that conform to
TheirPcol
the methodextraFunc()
and giving it a default implementation. This accomplishes the task of extending functionality for the objects conforming toTheirPcol
, and if you want it to apply to your own objects as well then you could conform your objects toTheirPcol
. In many situations, however, you want to keepMyPcol
as your primary protocol and just treatTheirPcol
as conforming toMyPcol
. Unfortunately, Swift does not currently support protocol extensions declaring conformance to other protocols.Using
TheirPcol
objects as if they wereMyPcol
In the use case (most likely your use case) where you really do need the separate existence of
MyPcol
, then as far as I am aware there is no clean way to do what you want yet. Here's a few working but non-ideal solutions:Wrapper around
TheirPcol
One potentially messy approach would be to have a
struct
orclass
like the following:You could theoretically use this struct as an alternative to casting, as in your example, when you need to make an existing object instance conform to
MyPcol
. Or, if you have functions that acceptMyPcol
as a generic parameter, you could create equivalent functions that take inTheirPcol
, then convert it toTheirPcolWrapper
and send it off to the other function taking inMyPcol
.Another thing to note is if you are being passed an object of
TheirPcol
, then you won't be able to create aTheirPcolWrapper
instance without first casting it down to an explicit type. This is due to some generics limitations of Swift. So, an object like this could be an alternative:This would mean you could create a
TheirPcolWrapper
instance without knowing the explicit type of theTheirPcol
you are given.For a large project, though, both of these could get messy really fast.
Extending individual objects using a child protocol
Yet another non-ideal solution is to extend each object that you know conforms to
TheirPcol
and that you know you wish to support. For example, suppose you know thatObjectA
andObjectB
conform toTheirPcol
. You could create a child protocol ofMyPcol
and then explicitly declare conformance for both objects, as below:Unfortunately, this approach breaks down if there are a large number of objects that you wish to support, or if you cannot know ahead of time what the objects will be. It also becomes a problem when you don't know the explicit type of a
TheirPcol
you are given, although you can usetype(of:)
to get a metatype.A note about Swift 4
You should check out Conditional conformances, a proposal accepted for inclusion in Swift 4. Specifically, this proposal outlines the ability to have the following extension:
While this is not quite what you are asking, at the bottom you'll find "Alternatives considered", which has a sub-section called "Extending protocols to conform to protocols", which is much more what you're trying to do. It provides the following example:
Then states the following:
While I realize you're not asking for the ability to have conditional conformances, this is the closest thing I could find regarding discussion of protocols being extended to conform to other protocols.