简体   繁体   中英

Swift generic type conforming to a variable subset of protocols

I am experimenting with protocols and how they can be used to decouple code, while taking advantage of other side effects of using protocols. Basically, what I am trying to do is the following:

An example could be a superset of API calls that is grouped into protocols by scope (eg "user API calls" and "settings API calls", or "non-mutating API calls" and "mutating API calls"). In this case, a consumer interested in using the API exposed by A should not necessarily know about the API's of B and C .

Consider the following protocols which mimic the above scenario:

protocol A {}
protocol B {}
protocol C {}

Then, given a set of protocols [A, B, C] , using a Factory class, I would like an instance of an API object that conforms to a subset of these:

let a = Factory<A>.create()
let ab = Factory<A, B>.create()
let bc = Factory<B, C>.create()

I have tried a handfuld of implementations such as:

class Factory<T: protocol<A, B, C>> {
    class func create() -> T {
        return ...
    }
}

However, initialising with let a = Factory<A>.create() yields the following error:

Using 'A' as a concrete type conforming to protocol 'A' is not supported

The same error occurs if Factory is defined as:

class Factory<T where T: A, T: B>

There are a few things that obviously fails:

  • <T: protocol<A, B, C>> and <T where T: A, T: B> requires the returned object to conform to both A , B , and C , not just a subset of them.
  • Given the error, it does not seem like it is even possible to "use a protocol as a concrete type conforming to a protocol".

In short, is it even possible to achieve what I am trying to?

I'd drop the use of generics in your case and I'd probably also look at protocol inheritance.

So, for example, a mutable protocol would inherit from the immutable protocol, because you want to be able to access as a minimum and both access and change in the alternate case.

The purpose of protocols is to abstract you from the underlying implementation classes. Generics are not really adding to that power in your example. Your factory (or factories) can simply provide a number of creation methods which return objects conforming to the various protocols.

To continue using generics means exposing the underlying implementation classes, and this is the cause for your error. You can't use a protocol for this because it isn't concrete, it's just the definition of what some concrete object is going to provide.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM