extension TypeName { ... } adds new functionality to an existing type — computed properties, instance/type methods, convenience initializers, subscripts, or conformance to a protocol — without touching the type's original source or requiring inheritance, working equally well on Apple's own built-in types (Int, String, Array) and types from third-party libraries. The one genuine, structural limitation: extensions cannot add STORED properties (actual new memory-backed state) to a type, only computed ones — since existing instances of that type were already allocated with a fixed size before the extension was even written, and retroactively growing that layout isn't possible.
Extending a built-in type with a computed property
Int's own source was never touched — squared is called exactly like a real built-in property, but it's entirely defined here, in this extension.
extension Int {
var squared: Int {
return self * self
}
}
print(5.squared) // 25 — called exactly like a built-in propertyAdding a method and an initializer
An extension can add genuinely new methods and even a convenience initializer to an existing type — String here gains an entirely new capability it didn't originally have.
extension String {
func shout() -> String {
return self.uppercased() + "!"
}
}
print("hello".shout()) // "HELLO!"The real limitation: no stored properties
Adding a stored property here is a genuine compile error — existing Int values across the entire program already have a fixed size in memory, and there's no way to retroactively grow that layout for a type defined elsewhere.
extension Int {
// var extraData: String = "" // COMPILE ERROR: extensions cannot add stored properties
var isEven: Bool { // fine — COMPUTED, not stored
return self % 2 == 0
}
}