Protocol '...' as a type cannot conform to '...' - A generic protocol of a generic protocol issue

1.2k views Asked by At

I've been playing around with Swift and SwiftUI. I've been trying to come up with a delegate based data store for various "data entities", the intention been to be able to replace the underlying data store implementations while keeping the code interface stable (this is an experimental code base, so I want to play with different data stores over time)

After a few attempts I came to the conclusion that much of the top level work was repeating (and I'd end up basically coping an pasting the boiler plate code), so, I thought I'd be clever and reduce and re-use the concepts, stupid me.

So, I started with a basic delegate, which holds the "core"/"common" functionality each delegate will need to be able to do.

    protocol SomeDelegateProtocol {
        associatedtype Item
        
        func performActionOn(_ item: Item)
        // Lots of common actions which can
        // be performed on entities
    }

Together with a concept of a "common" top level "manager" (implementations of which the app will work through - so we're decoupling the layers)

    class SomeManager<Delegate: SomeDelegateProtocol> {
        typealias Item = Delegate.Item
        
        let delegate: Delegate

        @Published var items: [Delegate.Item]
        // Other properties
        
        init(delegate: Delegate) {
            self.delegate = delegate
        }
        
        // Lots of boiler plate functionality
    }

Now, for each entity, we need to define a targeted delegate and manager

    protocol OtherItemProtocol {
        // Item enity properties
    }
    
    protocol OtherDelegateProtocol: SomeDelegateProtocol where Item == any OtherItemProtocol {
        // Specific functionality for this delegate
    }

    class OtherManager: SomeManager<OtherDelegateProtocol> {
        // Specific functionality for type of manager
    }

And this is where I run into problems. On my OtherManager, Xcode/Swift is complaining that:

Protocol 'OtherDelegateProtocol' as a type cannot conform to 'SomeDelegateProtocol'

Under Swift 5.7, I get a slightly different error

Type 'any OtherDelegateProtocol' cannot conform to 'SomeDelegateProtocol`

Just for (a little bit of) clarity. The majority of the app code will use implementations of SomeManager, for example, the code which needs to deal with OtherItemProtocol would work directly through OtherManager, not caring about "how" the entity is been stored. This approach is intended to reduce the amount of "repeating" code.

I've spent a couple of days trying to get my head around this issue, but I can't seem to find a solution which matches this particular problem. I'll probably just cry in the corner for a bit ... if any one has some ideas on how I might be able to resolve this, I'd appreciate it

(Yes, I've been Googling, but I've not found anything which matches a simular structure to what I've "dreamt" up)

Swift Swift

1

There are 1 answers

0
AudioBubble On

What you've written is shorthand for

class OtherManager: SomeManager<any OtherDelegateProtocol> { }

But protocols do not conform to themselves. any OtherDelegateProtocol does not meet the : SomeDelegateProtocol requirement. You need a concrete SomeDelegateProtocol type, instead.

To express that:

class OtherManager<Delegate: OtherDelegateProtocol>: SomeManager<Delegate> {

Also, Item == any OtherItemProtocol feels like Objective-C code. Maybe you meant this?

protocol OtherDelegateProtocol: SomeDelegateProtocol where Item: OtherItemProtocol {

Do you even need OtherDelegateProtocol, instead of an extension?

extension SomeDelegateProtocol where Item: OtherItemProtocol {
class OtherManager<Delegate: SomeDelegateProtocol>: SomeManager<Delegate> where Delegate.Item: OtherItemProtocol {

Do you even need a subclass? Typically, nobody ever needs a subclass in Swift.

extension SomeManager where Item: OtherItemProtocol {