iOS Interview - Understanding Dynamic Dispatch and Static Dispatch in Swift

April 09, 20244 min read#swift, #ios, #interview

In Swift, the concept of dispatch refers to the process of determining which implementation of a method or function to call at runtime. Swift supports two types of dispatch: dynamic dispatch and static dispatch. Understanding the differences between these two dispatch mechanisms is crucial for writing efficient and maintainable Swift code. In this blog post, we’ll explore dynamic dispatch and static dispatch in detail, along with code examples to illustrate their usage.

Dynamic Dispatch

Dynamic dispatch, also known as runtime polymorphism or late binding, is a mechanism where the implementation of a method is determined at runtime based on the actual type of the object. In Swift, classes use dynamic dispatch by default.

Here’s an example to demonstrate dynamic dispatch:

class Animal {
    func makeSound() {
        print("The animal makes a sound")
    }
}

class Dog: Animal {
    override func makeSound() {
        print("The dog barks")
    }
}

class Cat: Animal {
    override func makeSound() {
        print("The cat meows")
    }
}

let animals: [Animal] = [Animal(), Dog(), Cat()]

for animal in animals {
    animal.makeSound()
}

In this example, we define a base class Animal with a makeSound() method. We then create two subclasses, Dog and Cat, which override the makeSound() method with their specific implementations.

When we create an array of Animal objects and iterate over it, calling makeSound() on each object, the actual implementation of makeSound() is determined at runtime based on the actual type of the object. This is dynamic dispatch in action.

The output of the code will be:

The animal makes a sound
The dog barks
The cat meows

Dynamic dispatch allows for polymorphism and flexibility, as the same method call can exhibit different behavior depending on the actual type of the object.

Static Dispatch

Static dispatch, also known as compile-time polymorphism or early binding, is a mechanism where the implementation of a method or function is determined at compile-time based on the type information available. In Swift, static dispatch is used for structs, enums, and final classes.

Here’s an example to illustrate static dispatch:

final class Circle {
    func draw() {
        print("Drawing a circle")
    }
}

let circle = Circle()
circle.draw()

In this example, we define a final class Circle with a draw() method. Using final keyword prevents the class or the methods from being overridden by subclasses, and allows the compiler to directly call the methods without checking for overrides. Since Circle can’t be subclassed, the compiler knows exactly at runtime which draw method to invoke, hence it will use static dispatch for invoking draw.

The output of the code will be:

Drawing a circle

Static dispatch provides better performance compared to dynamic dispatch because the method implementation is determined at compile-time, avoiding the runtime overhead of dynamic dispatch.

Conclusion

Dynamic dispatch and static dispatch are two important concepts in Swift that determine how method implementations are resolved. Dynamic dispatch is used for classes and allows for runtime polymorphism, while static dispatch is used for structs, enums, and final classes, providing better performance by resolving method implementations at compile-time.

Understanding the differences between dynamic dispatch and static dispatch can help you make informed decisions when designing your Swift code, considering factors such as flexibility, performance, and maintainability.

Further reading:

Quick Drop logo

Profile picture

Personal blog by An Tran. I'm focusing on creating useful apps.
#Swift #Kotlin #Mobile #MachineLearning #Minimalist


© An Tran - 2024