tezvyn:

Associated Types: Making Protocols Generic

AI-drafted, machine-checkedSource: docs.swift.orgintermediate

Associated types make protocols generic. Think of them as a "fill-in-the-blank" type name. A protocol like `Sequence` has an `Element` type, which a conforming `Array<String>` fills in as `String`.

WHY IT EXISTS Protocols define a blueprint of methods and properties. But what if that blueprint needs to refer to another type that isn't known yet? Associated types solve this by allowing a protocol to be generic over types it uses, enabling powerful, flexible abstractions without specifying concrete types upfront.

THE MENTAL MODEL Think of an associated type as a placeholder or a "fill-in-the-blank" type name within a protocol. The protocol says, "Whoever adopts me must provide a concrete type for this placeholder I'm calling 'Item'." The conforming type then fills in that blank: "For me, 'Item' is a String."

HOW IT WORKS You declare a protocol with the associatedtype keyword, giving the placeholder a name, for example, associatedtype Element. Methods, properties, and subscripts within the protocol can then refer to this Element type. When a concrete type like a struct or class conforms to the protocol, it specifies the actual type for Element. This can be done explicitly with a typealias or, more commonly, implicitly by implementing a required method or property whose signature uses a specific type.

WHEN TO USE IT Use associated types when defining a protocol that describes a capability involving a type that isn't known until the protocol is adopted. The Swift Sequence and Collection protocols are prime examples; they have an Element associated type, allowing Array<String> and Set<Int> to share the same sequence-based logic while having different element types.

WHEN NOT TO USE IT Using a protocol with an associated type (often called a "PAT") has a major restriction: you cannot use it as the concrete type for a variable, property, or array element (e.g., var myItems: [Container] is forbidden if Container has an associated type). This is because the compiler needs to know the exact size and type of Item at compile time. To work around this, you must use generic constraints (e.g., func process<C: Container>(_ container: C)) or a technique called type erasure (e.g., AnySequence<Int>).

ONE CANONICAL EXAMPLE A Container protocol might require conforming types to be able to hold some kind of item. It would declare associatedtype Item and then define methods like append(_ item: Item) and a count property. A Stack struct that holds integers could conform to Container. By implementing append(_ item: Int), it implicitly tells the compiler that for Stack, the Item associated type is Int.

Read the original → docs.swift.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.