Why protocol-oriented programming matters in Swift - Performance Analysis
When using protocol-oriented programming, it is important to understand how the program's speed changes as it uses more data or more complex types.
We want to know how the use of protocols affects the time it takes for code to run as input grows.
Analyze the time complexity of the following Swift code using protocols.
protocol Drawable {
func draw()
}
struct Circle: Drawable {
func draw() {
print("Drawing Circle")
}
}
func drawAll(shapes: [Drawable]) {
for shape in shapes {
shape.draw()
}
}
This code defines a protocol and a struct that follows it, then draws all shapes in a list by calling their draw method.
Look for loops or repeated calls that affect performance.
- Primary operation: Looping through the array of shapes and calling draw() on each.
- How many times: Once for each shape in the input array.
As the number of shapes increases, the number of draw calls grows directly with it.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 draw calls |
| 100 | 100 draw calls |
| 1000 | 1000 draw calls |
Pattern observation: The work grows evenly as the input grows; doubling shapes doubles work.
Time Complexity: O(n)
This means the time to draw all shapes grows in a straight line with the number of shapes.
[X] Wrong: "Using protocols makes the code slower because of extra overhead in method calls."
[OK] Correct: Protocol calls are optimized by Swift, and the main time cost comes from how many times you call methods, not from using protocols themselves.
Understanding how protocol-oriented code scales helps you write clean, reusable code without worrying about hidden slowdowns as your app grows.
"What if the drawAll function used recursion instead of a loop? How would the time complexity change?"
Practice
Solution
Step 1: Understand what protocols represent
Protocols specify a set of methods and properties that a type must have, acting as a blueprint.Step 2: Differentiate protocols from data storage
Protocols do not store data themselves; they only define behavior and requirements.Final Answer:
To define a blueprint of methods and properties that a type must implement -> Option AQuick Check:
Protocols = Blueprint of behavior [OK]
- Thinking protocols store data
- Confusing protocols with classes or structs
- Assuming protocols manage memory
Drivable in Swift?Solution
Step 1: Recall protocol declaration syntax
Protocols are declared using the keywordprotocolfollowed by the name and curly braces.Step 2: Identify correct method declaration inside protocol
Inside protocols, methods are declared without implementation, just the signature.Final Answer:
protocol Drivable { func drive() } -> Option DQuick Check:
Use 'protocol' keyword and method signature [OK]
- Using class or struct instead of protocol
- Trying to implement method inside protocol
- Incorrect keyword order
protocol Greetable {
func greet() -> String
}
struct Person: Greetable {
func greet() -> String {
"Hello!"
}
}
let p = Person()
print(p.greet())Solution
Step 1: Check protocol and struct conformance
The structPersonconforms toGreetableand implementsgreet()returning "Hello!".Step 2: Understand the print statement output
Callingp.greet()returns "Hello!", which is printed.Final Answer:
Hello! -> Option CQuick Check:
Protocol method implemented returns "Hello!" [OK]
- Assuming protocol methods print automatically
- Thinking missing implementation error occurs
- Confusing method name with output
protocol Runnable {
func run()
}
struct Athlete: Runnable {
// Missing run() implementation
}
let athlete = Athlete()
athlete.run()Solution
Step 1: Check protocol requirements
The protocolRunnablerequires arun()method to be implemented.Step 2: Verify struct conformance
The structAthletedoes not implementrun(), so it does not conform properly.Final Answer:
Athlete struct must implement run() method -> Option AQuick Check:
Protocol methods must be implemented in conforming types [OK]
- Assuming protocols can't be used with structs
- Thinking run() must return a value
- Believing instance creation is the error
Solution
Step 1: Understand protocol-oriented programming benefits
Protocols with default implementations allow behavior sharing without inheritance.Step 2: Evaluate options for reuse and maintenance
Extending a protocol with defaultlog()method lets many types reuse logging easily and maintain code in one place.Final Answer:
Define a protocolLoggablewith alog()method, then extend it with default implementation -> Option BQuick Check:
Protocols + extensions = reusable, maintainable code [OK]
- Relying on inheritance instead of protocols
- Duplicating code in each class
- Using global variables for behavior
Ready to prove it?
Pass the test and this pattern moves unknown
