Protocol Default Implementations / Protocol Composition
Swift protocols support default implementations added via extensions. You can also use protocol composition to combine multiple protocols, and the any and some keywords to work with abstract types.
Syntax
// Default implementation for a protocol
extension ProtocolName {
func methodName() { /* implementation */ }
}
// Protocol composition
func functionName(param: ProtocolA & ProtocolB) { }
// any (existential type)
var variableName: any ProtocolName
// some (opaque type)
func functionName() -> some ProtocolName { }
Syntax list
| Syntax | Description |
|---|---|
| extension P { func f() {} } | Adds a default implementation to protocol P. Conforming types work without implementing it themselves. |
| A & B | Protocol composition that requires conformance to both protocol A and protocol B. |
| any P | An existential type that can hold any value conforming to protocol P (Swift 5.7+). |
| some P | An opaque type that returns a specific concrete type conforming to protocol P, hiding the type details from the caller. |
Sample code
protocol Greetable {
var name: String { get }
func greet() -> String
}
// Add a default implementation via extension
extension Greetable {
func greet() -> String {
return "Hello, I'm \(name)!"
}
}
protocol Farewell {
func farewell() -> String
}
struct Person: Greetable, Farewell {
var name: String
// greet() uses the default implementation
func farewell() -> String { "Goodbye from \(name)!" }
}
// Protocol composition
func introduce(_ x: Greetable & Farewell) {
print(x.greet())
print(x.farewell())
}
let p = Person(name: "Hanako")
introduce(p)
// any (existential type)
var anyone: any Greetable = Person(name: "Jiro")
print(anyone.greet())
Overview
Default protocol implementations are provided using extensions. If a conforming type defines a method with the same name, it overrides the default; otherwise, the default is used. This approach significantly reduces code duplication.
Protocol composition (&) is used when you need a value to conform to multiple protocols simultaneously. Unlike inheritance, it works with classes, structs, and enums alike.
any is an existential type introduced in Swift 5.7 for type erasure. Because it incurs a boxing cost, consider using some or a concrete type in performance-sensitive code. some hides the return type from the caller while letting the compiler track the concrete type, which is why it is widely used in SwiftUI.
If you find any errors or copyright issues, please contact us.