Swift Extensions
An extension adds new functionality to an existing type — even one you did not write, like Swift's own String or Int. Extensions let you keep related code grouped together without modifying the original source file.
The Renovation Analogy
┌──────────────────────────────────────────────────┐
│ Extension = Home Renovation │
│ │
│ Original house: living room, bedroom, kitchen │
│ After extension: + home office, + gym │
│ │
│ The original structure stays intact. │
│ You add new rooms without tearing walls. │
└──────────────────────────────────────────────────┘
Adding a Method to an Existing Type
extension String {
func shout() -> String {
return self.uppercased() + "!!!"
}
}
let message = "hello swift"
print(message.shout()) // HELLO SWIFT!!!
The String type now has a shout() method everywhere in your project. You added it without touching Swift's source code.
Adding a Method to Int
extension Int {
func squared() -> Int {
return self * self
}
var isEven: Bool {
return self % 2 == 0
}
}
print(7.squared()) // 49
print(8.isEven) // true
print(3.isEven) // false
Adding an Initializer via Extension
struct Point {
var x: Double
var y: Double
}
extension Point {
init(value: Double) {
self.x = value
self.y = value
}
}
let p = Point(value: 5.0)
print(p.x, p.y) // 5.0 5.0
Extensions can add new initializers to existing types. The original memberwise initializer stays available alongside the new one.
Organising Code with Extensions
struct User {
var name: String
var age: Int
}
// Core logic
extension User {
func greet() {
print("Hello, I am \(name).")
}
}
// Validation logic
extension User {
func isAdult() -> Bool {
return age >= 18
}
}
// Display logic
extension User: CustomStringConvertible {
var description: String {
return "User(\(name), \(age))"
}
}
let u = User(name: "Arjun", age: 22)
u.greet()
print(u.isAdult()) // true
print(u) // User(Arjun, 22)
Extension as a Code Organiser
┌──────────────────────────────────────────────────┐
│ Without extensions: With extensions: │
│ │
│ struct User { struct User { ... } │
│ // 200 lines extension User { greet } │
│ // all mixed extension User { validate}│
│ } extension User { display }│
│ │
│ Each extension groups one concern. │
│ Much easier to read and maintain. │
└──────────────────────────────────────────────────┘
Protocol Conformance via Extension
protocol Printable {
func printInfo()
}
struct Product {
var name: String
var price: Double
}
extension Product: Printable {
func printInfo() {
print("\(name) costs ₹\(price)")
}
}
let item = Product(name: "Notebook", price: 49.0)
item.printInfo() // Notebook costs ₹49.0
Adding protocol conformance through an extension keeps the struct definition clean. The protocol requirement and its implementation live together in the extension.
What Extensions Cannot Do
- They cannot add stored properties to existing types
- They cannot override existing methods
- They cannot add designated initializers to classes (only convenience initializers)
These limits keep extensions predictable. You enhance a type without disrupting how it already works.
