Swift  

Understanding the Difference Between Struct and Class in Swift

Swift provides two foundational types for creating custom data models: struct and class. While they can look similar in syntax, their behavior is fundamentally different, especially in how they handle memory, identity, and mutability.

Let’s break it down clearly with real examples.

🔵 Class

Class is a reference type.

When you assign one instance to another, both refer to the same memory.

class Person {
    var name: String

    init(name: String) {
        self.name = name
    }
}
let p1 = Person(name: "Alice")
let p2 = p1
p2.name = "Bob"
print(p1.name) // Output: Bob

A change in one reflects in the other because both point to the same object.

Classes support inheritance

class Animal {
    func sound() -> String {
        return "Generic sound"
    }
}

class Dog: Animal {
    override func sound() -> String {
        return "Bark"
    }
}
print(Dog().sound()) // Output: Bark

Inheritance allows creating hierarchies and shared behavior.

Classes have an identity you can check if two references are pointing to the same instance using ===.

let a = Person(name: "Eva")
let b = a
print(a === b) // Output: true

They’re not just equal, they’re the same object in memory.

Class instances can have immutable properties and still be modified if declared with let.

class Box {
    var weight = 10
}

let box = Box()
box.weight = 20  // ✅ This works

Even though the box is declared with let, you can still modify its properties.

🟢 Struct

Struct is a value type.

struct Car {
    var brand: String
}

var car1 = Car(brand: "Tesla")
var car2 = car1
car2.brand = "BMW"

print(car1.brand) // Output: Tesla

Each assignment creates a copy. Changes to one don’t affect the other.

Struct doesn’t support inheritance.

struct Animal {}

// struct Dog: Animal {} ❌ Error

// ✅ Use protocol instead
protocol Walkable {
    func walk()
}
struct Dog: Walkable {
    func walk() {
        print("Dog walking")
    }
}

Use protocol-oriented design for code reuse in structs.

Structs don’t have identity; comparison is based on value.

struct Point: Equatable {
    var x: Int
    var y: Int
}

let p1 = Point(x: 2, y: 3)
let p2 = Point(x: 2, y: 3)

print(p1 == p2) // Output: true

Equality is based on property values, not memory references.

Structs are immutable by default unless you use mutating.

struct Counter {
    var count = 0

    mutating func increment() {
        count += 1
    }
}

var counter = Counter()
counter.increment()
print(counter.count) // Output: 1

Without mutating, struct methods can't change properties.

✅ Conclusion

Choose struct if,

  • You want value semantics (copies).
  • Your data type is small and doesn’t need inheritance.
  • You prefer safer, immutable design by default.

Choose a class if,

  • You need shared instances and identity.
  • You require inheritance.
  • You want dynamic dispatch and flexibility.