23

In the new Swift API design guidelines, the commonly-used Type suffix for protocols is being dropped. While this is easy to do for protocols that are stand-alone (SequenceType becomes Sequence), I'm not sure how to update my APIs in which a protocol provides the base for an implementation. Here's some examples from popular frameworks:

  • The Result µframework provides Result, a concrete success/fail enumeration, and ResultType, a generic base protocol for a success/fail type, to which Result conforms.
  • ReactiveCocoa's main types are Signal and SignalProducer, which are backed by SignalType and SignalProducerType.

In both cases, much of the implementation is in extensions of the protocols, allowing extensions to use the full power of type constraints, and allowing the implementations to be generic. This is different from the case of protocols with AnySequence-style type-erasing types: you aren't really expected to implement these protocols on your own, or unify disparate types.

JHZ
  • 1,158
  • 1
  • 10
  • 15

1 Answers1

21

I would advise using the suffix Protocol. This is consistent with how the standard library have stripped the Type suffix from protocols, as stated in SE-0006:

On high level, the changes can be summarized as follows.

  • Strip Type suffix from protocol names. In a few special cases this means adding a Protocol suffix to get out of the way of type names that are primary (though most of these we expect to be obsoleted by Swift 3 language features).

For example, GeneratorType was renamed to IteratorProtocol.

And, for example, is also how both Result & ReactiveSwift have updated their APIs for Swift 3. ResultType was renamed to ResultProtocol (in this commit), and SignalType was renamed to SignalProtocol, and SignalProducerType was renamed to SignalProducerProtocol (in this commit).

Although it's worth noting that in a vast majority of these cases, such protocols only exist as a workaround for the lack of parameterised extensions.

For example, we cannot currently say:

struct SomeGenericThing<T> {
    var value: T
}

extension <T> Array where Element == SomeGenericThing<T>, T : Comparable {

}

But introducing a protocol allows us to realise the generic placeholder(s) as associated type(s), which we can then use in constraints:

protocol SomeGenericThingProtocol {
    associatedtype T
    var value: T { get set }
}

struct SomeGenericThing<T> : SomeGenericThingProtocol {
    var value: T
}

extension Array where Element : SomeGenericThingProtocol, Element.T : Comparable {
    // ...
}

Therefore once parameterised extensions are supported, we'll be able to do away with such protocols.

Hamish
  • 78,605
  • 19
  • 187
  • 280