ProgrammingSwift Middle/Lead

What is protocol composition in Swift, how does it work in practice, and when should it be used instead of multiple inheritance or regular protocol usage?

Pass interviews with Hintsage AI assistant

Answer.

Protocol composition is a mechanism in Swift that allows creating a type that must conform to several protocols at the same time. This is an alternative way to replace multiple inheritance, which is not available for classes in Swift.

Background

Objective-C supported multiple inheritance only for protocols, but not for classes. Swift continues this tradition, emphasizing protocols and their combinations to build new abstractions.

Problem

Programmers often face the challenge of creating a type whose behavior is defined by several abstractions. Multiple inheritance inevitably leads to hierarchy conflicts, which is safely resolved in Swift using protocols and protocol composition.

Solution

In Swift, protocols can be combined using the '&' operator. This allows creating variables or function parameters that must conform to multiple protocols at once.

Code example:

protocol Drivable { func drive() } protocol Flyable { func fly() } struct FlyingCar: Drivable, Flyable { func drive() { print("Driving") } func fly() { print("Flying") } } func testVehicle(_ vehicle: Drivable & Flyable) { vehicle.drive() vehicle.fly() } testVehicle(FlyingCar())

Key features:

  • The '&' operator allows combining multiple protocols for a variable or function parameter
  • Works for classes, structs, and enums
  • Allows explicitly describing required behavior without creating intermediate types

Trick questions.

Can an object that implements only one of the protocols be passed to a parameter with protocol composition?

No, the object must implement all the protocols involved in the composition; otherwise, the compiler will raise an error.

Code example:

// struct Car: Drivable {} — cannot be passed to testVehicle since fly() is not implemented

Does protocol composition work with types, not just with values?

Protocol composition applies to values (variables, function parameters), but is not used when defining the object's type (for example, you cannot declare a new type as some "composition" of protocols — only a variable).

Code example:

var obj: SomeProtocol & AnotherProtocol // acceptable // typealias MyType = SomeClass & AnotherProtocol // error

Can classes and protocols be combined through '&'?

Yes, but with one limitation: only one class type (class or its subclass) can be on the left side, and the rest must be protocols; otherwise, the compiler will raise an error.

Code example:

class A {} protocol B {} // func f(obj: A & B) {} // acceptable // func f(obj: A & AnotherClass & B) {} // error! Only one class type is allowed

Common mistakes and anti-patterns

  • Expecting behavior similar to multiple inheritance of classes
  • Using composition unnecessarily when one protocol is sufficient
  • Breaking contracts when using external libraries and protocol composition

Real-world example

Negative case

In a project where data is passed between layers using objects with protocol composition, even though a single protocol would suffice:

func present(item: Displayable & Serializable) { ... }

Pros:

  • Flexible and extensible interface Cons:
  • Complexity and confusion if most passed objects do not require all capabilities

Positive case

Using protocol composition only in explicit cases — for example, processing objects that simultaneously support Codable and Identifiable for generalized serialization:

func save<T: Codable & Identifiable>(_ item: T) { ... }

Pros:

  • Clear description of type requirements
  • Minimization of errors Cons:
  • May slightly complicate function signatures