Differences between type-inheritance clause & protocol composition syntax?

Four years ago, Swift 4 introduced protocol compositions to Swift via SE-0156, with a review in early 2017, which finally added a long-awaited Obj. C feature via the new single-ampersand syntax for type declarations:

protocol A{}
protocol B{}
class C: A & B {}

However, for reasons that weren't immediately apparent from scanning the old review thread, we also kept what our current documentation describes as a "type inheritance list", which uses a comma separator as opposed to an ampersand:

class D: A, B {} 
class E {}
class F: E, A, B {} 

You can even combine them:

class E {}
class F: E, A, B {}
class G: E & A, B {} // ew
class H: E, A & B {} // yuck
class I: A & B & E {} // if it's all ampersands, the class doesn't have to be first
class J: A & B, E {} // won't compile bc there's a comma and the class isn't first

From what I can tell, these are the differences between the comma and ampersand syntax:

  • if a comma is present, and a class is in the list of types, then the compiler requires that the the class appear first in the list
  • the comma-separated variety can only appear in a type inheritance clause, but not in the type of a variable, typealias, tuple param, or function param

This begs the question of, why would you ever choose comma over ampersand for a type inheritance clause? Is it a purely stylistic thing or is there some functional difference that I'm missing?

Thank you for any insights!

4 Likes
4 Likes

Whlie it’s not a technical difference, if you use type aliases, then you might need to use both, sort of.

protocol P { … }
protocol A { …. }
protocol B { …. }
typealias MyCombo = P & A

struct S1: P { … }
struct S2: MyCombo, B { … }
struct S3: MyCombo { … }

I don't understand. You can replace the comma with an ampersand in this line too:

struct S2: MyCombo, B { … }

This seems kosher:

struct S2: MyCombo & B { … }

It's an old thread, but I'm not sure what the caveat was. Is there any reason against just using ampersands everywhere?

Update: This SO thread provides a bit more detail.

It doesn’t work for enum raw types, cause those are special.

I’d argue it’s poor style for classes to include their superclass via composition unless there’s a really good reason, but I believe it will work. EDIT: through a typealias, I mean. It doesn’t seem much different if written explicitly in the inheritance list.

Between lists of protocols I don’t think it matters.

2 Likes

@jrose - Thanks for the clarification. Much appreciated.