Inheritance Rules

Protocols can refine other protocols. A type that conforms to the refined protocol automatically owes the requirements of the parent.

Refinement

protocol Equatable { func isEqual(to other: Self) -> Bool } protocol Comparable: Equatable { func compare(other: Self) -> Ordering }

Comparable refines Equatable. A type conforming to Comparable must satisfy bothisEqual and compare. Anywhere a type parameter is constrained to Equatable, a Comparable type satisfies it.

Combining protocols

A protocol can inherit from many. Stack them:

protocol Sortable: Comparable, Hashable { // Sortable's own requirements, if any }

A Sortable type satisfies Comparable, Hashable, and anything Sortable adds.

Composition without naming

When a function needs more than one capability and you don't want to invent a new protocol, list them:

protocol Drawable { func draw() } func process[T](item: T) where T: Drawable, T: Hashable { /* ... */ }

Same effect as creating a protocol DrawableAndHashable: Drawable, Hashable {}, without the bookkeeping.

When to refine, when to compose

  • Refine when the relationship is permanent and meaningful — Comparable types are always Equatable.
  • Compose at the use site when you just happen to need two capabilities for one function.

Don't invent intermediate protocols just to give a name to a where clause.