In my swift project I have a case where I use protocol inheritance as follow
protocol A : class{
}
protocol B : A{
}
What Im trying to achieve next is declaring another protocol with associated type, a type which must inherit from protocol A
. If I try to declare it as :
protocol AnotherProtocol{
associatedtype Type : A
weak var type : Type?{get set}
}
it compiles without errors but when trying to adopt AnotherProtocol
in the following scenario:
class SomeClass : AnotherProtocol{
typealias Type = B
weak var type : Type?
}
compilation fails with error claiming that SomeClass
does not conform to AnotherProtocol
. If I understood this correctly it means that B
does not adopt A
while Im trying to declare and asking you on how to declare an associated type which inherits from protocol A
?
I made the above assumption based on fact that the following scenario compiles just fine
class SomeDummyClass : B{
}
class SomeClass : AnotherProtocol{
typealias Type = SomeDummyClass
weak var type : Type?
}
This is pretty interesting. It appears that once you constrain the type of an
associatedtype
in a given protocol, you need to provide a concrete type in the implementation of that protocol (instead of another protocol type) – which is why your second example worked.If you remove the
A
constraint on the associated type, your first example will work (minus the error about not being able to useweak
on a non-class type, but that doesn’t seem to be related).That all being said, I can't seem to find any documentation in order to corroborate this. If anyone can find something to back this up with (or completely dispute it), I’d love to know!
To get your current code working, you can use generics. This will actually kill two birds with one stone, as both your code will now compile and you'll benefit from the increased type safety that generics bring (by inferring the type you pass to them).
For example:
Edit: It appears the above solution won't work in your particular case, as you want to avoid using concrete types. I'll leave it here in case it's useful for anyone else.
In your specific case, you may be able to use a type erasure in order to create a pseudo concrete type for your
B
protocol. Rob Napier has a great article about type erasures.It's a bit of a weird solution in this case (as type erasures are normally used to wrap protocols with
associatedtypes
), and it's also definitely less preferred than the above solution, as you have to re-implement a 'proxy' method for each method in yourA
&B
protocols – but it should work for you.For example:
You can now use the
AnyB
type in place of using theB
protocol type, without making it any more type restrictive.