5

Is there a difference between these two in Swift?

  • protocol ABProtocol: AProtocol, BProtocol {}
  • typealias ABProtocol = AProtocol&BProtocol
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Martin
  • 1,112
  • 1
  • 11
  • 31

2 Answers2

4

To make things clearer, I will rename the second one to:

typealias ABProtocolIntersection = AProtocol & BProtocol

I can think of two differences off the top of my head.

If your type conform to AProtocol and BProtocol, the type is automatically a subtype of ABProtocolIntersection, but it does not automatically conform to ABProtocol. After all, ABProtocol is a totally different protocol.

Example:

class Foo: AProtocol, BProtocol { ... }

func foo<T: ABProtocolIntersection>(type: T.Type) {  }
func bar<T: ABProtocol>(type: T.Type) { }

foo(type: Foo.self) // works
bar(type: Foo.self) // error

Another difference is that you can put extensions on ABProtocol, but not ABProtocolIntersection:

extension ABProtocol { } // OK

extension ABProtocolExtension { } // error

This is because ABProtocolIntersection is a non-nominal type, similar to types like (Int, Int) or (Int) -> String. See also: What is a 'non-nominal type' in Swift?

Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

Yes there is a difference. The former defines a new protocol to which types must conform when it is used. The latter only defines a "placeholder" for AProtocol&BProtocol

Consider the following code:

protocol AProtocol{}
protocol BProtocol{}

protocol ABProtocol1: AProtocol, BProtocol {}
typealias ABProtocol2 = AProtocol & BProtocol

func f1(value: ABProtocol1) {}
func f2(value: ABProtocol2) {}

Arguments to f1 must conform to ABProtocol1 but arguments to f2 can conform to AProtocol and BProtocol. You do not need to explicitly conform types to ABProtocol2. For example:

struct A: AProtocol, BProtocol
{
}

f1(value: A()) // Error!
f2(value: A()) // OK
JeremyP
  • 84,577
  • 15
  • 123
  • 161