Multiple type restrictions in Swift

Let's say I have these protocols:

protocol SomeProtocol { } protocol SomeOtherProtocol { } 

Now, if I need a function that accepts a generic type, but this type must match SomeProtocol , I could do:

 func someFunc<T: SomeProtocol>(arg: T) { // do stuff } 

But is there a way to add a type restriction for multiple protocols?

 func bothFunc<T: SomeProtocol | SomeOtherProtocol>(arg: T) { } 

Similar things use commas, but in this case it will start a different type of declaration. Here is what I have tried.

 <T: SomeProtocol | SomeOtherProtocol> <T: SomeProtocol , SomeOtherProtocol> <T: SomeProtocol : SomeOtherProtocol> 
+91
swift
Jun 06 '14 at 19:17
source share
4 answers

You can use where where , which allows you to specify as many requirements as you want (all this must be done), separated by commas

Swift 2:

 func someFunc<T where T:SomeProtocol, T:SomeOtherProtocol>(arg: T) { // stuff } 

Swift 3 and 4:

 func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) { // stuff } 

or a more powerful where clause:

 func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol{ // stuff } 

You can, of course, use the composition of the protocol (for example, protocol<SomeProtocol, SomeOtherProtocol> ), but it is slightly less flexible.

Using where allows you to handle cases where multiple types are involved.

You can still draw up protocols for reuse in several places, or just give the compiled protocol a meaningful name.

+182
Jun 06 '14 at 19:27
source share

You have two options:

  • You use where clause , as stated in Jiaaro's answer:

     func someFunc<T where T : SomeProtocol, T : SomeOtherProtocol>(arg: T) { // do stuff } 
  • You're using

+72
Jun 11 '14 at 14:24
source share

There are some changes to the evolution of Swift 3.0. Now our two options look a little different.

Using the where clause in Swift 3.0:

The where clause has now been moved to the end of the function signature for improved readability. Thus, the inheritance of several protocols now looks like this:

 func someFunc<T>(arg: T) where T:SomeProtocol, T:SomeOtherProtocol { } 

Using the protocol<> construct in Swift 3.0:

Composition using the protocol<> construct is deprecated. Previously protocol<SomeProtocol, SomeOtherProtocol> now looks like this:

 func someFunc<T:SomeProtocol & SomeOtherProtocol>(arg: T) { } 

References

More information about the changes for where is here: https://github.com/apple/swift-evolution/blob/master/proposals/0081-move-where-expression.md

And more about the changes to the protocol design <> are given here: https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md

+15
Aug 22 '16 at 7:31
source share

Swift 3 offers up to 3 different ways to declare your function.

 protocol SomeProtocol { /* ... */ } protocol SomeOtherProtocol { /* ... */ } 

1. Using the & operator

 func someFunc<T: SomeProtocol & SomeOtherProtocol>(arg: T) { /* ... */ } 

2. Using the where clause

 func someFunc<T>(arg: T) where T: SomeProtocol, T: SomeOtherProtocol { /* ... */ } 

3. Using the where operator and the & operator

 func someFunc<T>(arg: T) where T: SomeProtocol & SomeOtherProtocol { /* ... */ } 



Also note that you can use typealias to shorten function declarations.

 typealias RequiredProtocols = SomeProtocol & SomeOtherProtocol func someFunc<T: RequiredProtocols>(arg: T) { /* ... */ } 
+8
03 Sep '16 at 7:03
source share



All Articles