Associated Types

An associated type is a type member of a protocol. The protocol declares that a type exists; each conforming type picks a concrete one.

Declaring

protocol Container { type Item func count() -> Int func item(at index: Int) -> Item }

Item is a placeholder. Any type conforming to Container will choose what Item becomes.

Conforming

<!-- sample: continue --> struct Stack[T] { var items: [T] } extend Stack[T]: Container { type Item = T public func count() -> Int { self.items.count } public func item(at index: Int) -> T { self.items(index) } }

The type Item = T line picks the concrete type. The declaration is explicit — Kestrel does not infer Item from the method signatures, and leaving it out is an error (E455), even though item(at:) already returns T.

Using associated types in generic code

Refer to a protocol's associated type with dotted access:

<!-- sample: continue --> func first[C](in container: C) -> Optional[C.Item] where C: Container { if container.count() > 0 { .Some(container.item(at: 0)) } else { .None } }

C.Item is whatever the conforming type picked. first works on Stack[User] (returning Optional[User]) and Stack[Int] (returning Optional[Int]).

Constraining associated types

A where clause on an extension can constrain an associated type:

<!-- sample: continue --> extend Container where Item: Comparable { public func max() -> Optional[Item] { if self.count() == 0 { return .None }; var best = self.item(at: 0); for i in 1..<self.count() { let candidate = self.item(at: i); if candidate > best { best = candidate }; } .Some(best) } }

max() exists only on containers whose items are Comparable. This is what lets generic code do real work: combining "the item type, whatever it is" with "and that item type can be compared."

Why bother?

The alternative would be making every protocol generic — Container[T] instead of Container { type Item }. That works but forces every consumer of the protocol to thread T through. Associated types let the protocol stay un-parameterized at the call site while still being type-safe.

A useful rule: if the type parameter is part of what the protocol means, it's an associated type. If it's part of which protocol you want, it's a generic parameter.