What are the performance characteristics of dynamic vs. static dispatch when using protocols (POP) versus class inheritance (OOP)?
iOS interview question for Intermediate practice.
Answer
Performance Characteristics of Dynamic vs. Static Dispatch in Swift When dealing with protocols and inheritance in Swift, understanding the performance implications of dynamic and static dispatch is crucial for writing efficient code. Let's break down the differences: 1. Static Dispatch (OOP with Class Inheritance): Mechanism: The compiler knows the exact method to call at compile time. This is because the type of the object is known. It directly calls the method within the object's class. Performance: Very fast. There's no runtime overhead for determining which method to execute. Example: swift class Animal { func makeSound() { print("Generic animal sound") } } class Dog: Animal { override func makeSound() { print("Woof!") } } let myDog = Dog() myDog.makeSound() // Static dispatch: "Woof!" is printed 2. Dynamic Dispatch (POP with Protocols): Mechanism: The compiler doesn't know the exact method to call until runtime. This is because you are dealing with a protocol which may be adopted by multiple classes. A runtime lookup is performed to find the correct implementation based on the object's type. Performance: Slower than static dispatch due to the runtime overhead of the lookup. However, the performance penalty is often small and may be negligible depending on the scenario. Example: swift protocol SoundProducer { func makeSound() } class Cat: SoundProducer { func makeSound() { print("Meow!") } } class Bird: SoundProducer { func makeSound() { print("Chirp!") } } let myCat: SoundProducer = Cat() myCat.makeSound() // Dynamic dispatch: "Meow!" is printed 3. Comparison: | Feature | Static Dispatch (OOP) | Dynamic Dispatch (POP) | |----------------|-----------------------|------------------------| | Compile-time | Yes | No | | Runtime lookup | No | Yes | | Performance | Faster | Slower | | Flexibility | Less | More | Best Practices: Prioritize static dispatch: When possible, favor class inheritance and static dispatch for better performance, especially in performance-critical sections of your app. Use protocols judiciously: Use protocols where flexibility and polymorphism are essential. The minor performance overhead of dynamic dispatch is usually acceptable unless you're working with extremely high-performance code. Profile your app: If performance is a major concern, profile your application to identify bottlenecks. Don't prematurely optimize without data. In Summary: Static dispatch is generally faster because it resolves the method call at compile time, whereas dynamic dispatch involves a runtime lookup that introduces a small overhead. Choose the approach that best balances performance and flexibility for your specific use case.
Explanation
The performance difference between static and dynamic dispatch is often negligible in modern hardware, so optimization should focus on algorithm efficiency rather than solely this distinction.