Default Methods
A protocol can supply a default implementation for its requirements. Any conforming type gets the default for free; types that want different behavior override it.
Defaults via extension
Provide a default by writing the body in an extend block on the protocol:
protocol Greeter {
func name() -> String
func greet()
}
extend Greeter {
public func greet() {
println("Hello, \(self.name())!");
}
}
Now any type that conforms to Greeter only has to implement name. greet comes from the default:
struct Cat {
let nickname: String
}
extend Cat: Greeter {
public func name() -> String { self.nickname }
// greet is inherited
}
Cat(nickname: "Mittens").greet(); // "Hello, Mittens!"
Overriding the default
A conforming type can supply its own implementation, which takes precedence:
<!-- sample: continue -->struct Robot {
let model: String
}
extend Robot: Greeter {
public func name() -> String { self.model }
public func greet() {
println("INITIALIZING. UNIT \(self.model) ONLINE.");
}
}
Why defaults matter
Defaults are how protocols stay ergonomic as they grow. Adding a new requirement to an existing protocol normally breaks every conforming type — but if the new requirement has a default, existing conformances keep compiling and authors opt in to overriding when they need different behavior. It's the difference between a protocol that's safe to evolve and one that becomes a standing tax on every conforming type.
The flip side: a default that doesn't make sense for every type isn't really a default — it's a footgun. If three out of five conforming types want different behavior, make it a requirement instead.