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.

Leave a Comment

Your email address will not be published. Required fields are marked *