Protocol as types in Swift - Time & Space Complexity
When we use protocols as types in Swift, we want to know how the program's running time changes as we work with more objects that follow the protocol.
We ask: How does the time to call protocol methods grow when we have many such objects?
Analyze the time complexity of the following code snippet.
protocol Drawable {
func draw()
}
func drawAll(shapes: [Drawable]) {
for shape in shapes {
shape.draw()
}
}
This code defines a protocol and a function that calls the draw method on each object in a list of protocol types.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calling
draw()on each object in the array. - How many times: Once for each object in the
shapesarray.
As the number of shapes grows, the total calls to draw() grow the same way.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 calls to draw() |
| 100 | 100 calls to draw() |
| 1000 | 1000 calls to draw() |
Pattern observation: The number of operations grows directly with the number of shapes.
Time Complexity: O(n)
This means the time to run the function grows in a straight line as you add more shapes.
[X] Wrong: "Using a protocol as a type makes the code slower in a way that changes the time complexity."
[OK] Correct: Calling methods on protocol types does add a small fixed cost, but this cost stays the same per call and does not change how the total time grows with more objects.
Understanding how using protocols as types affects performance helps you explain your design choices clearly and shows you know how code structure relates to speed.
What if the draw() method itself contained a loop over a collection? How would that change the overall time complexity?
Practice
protocol as a type in Swift?Solution
Step 1: Understand what a protocol defines
A protocol defines a set of rules or features that a type must implement.Step 2: Using protocol as a type
When a protocol is used as a type, any object that implements those rules can be assigned to that type.Final Answer:
Any object that follows the protocol's rules can be used as that type. -> Option AQuick Check:
Protocol as type means flexible object use = A [OK]
- Thinking protocols only apply to classes
- Believing protocols define stored properties
- Confusing protocol usage with inheritance
Drawable?Solution
Step 1: Understand protocol type declaration
To declare a variable of a protocol type, use the protocol name without parentheses or brackets.Step 2: Analyze options
var shape: Drawable correctly declares a variable of type Drawable. Options A and B incorrectly try to instantiate a protocol, which is not allowed. var shape: Drawable[] uses invalid syntax.Final Answer:
var shape: Drawable -> Option AQuick Check:
Protocol type variable = var name: ProtocolName [OK]
- Trying to instantiate a protocol directly
- Using parentheses after protocol name
- Using array brackets incorrectly
protocol Greetable {
func greet() -> String
}
struct Person: Greetable {
func greet() -> String {
"Hello"
}
}
let greeter: Greetable = Person()
print(greeter.greet())Solution
Step 1: Understand protocol conformance
Person struct conforms to Greetable and implements greet() returning "Hello".Step 2: Using protocol as type and calling method
Variable greeter is of type Greetable but holds a Person instance, so calling greet() returns "Hello".Final Answer:
Hello -> Option DQuick Check:
Protocol method call returns implemented string = Hello [OK]
- Expecting protocol name or method name as output
- Thinking protocol cannot be used as variable type
- Confusing compile error with runtime behavior
protocol Vehicle {
func start()
}
class Car: Vehicle {
func start() {
print("Car started")
}
}
var myVehicle: Vehicle = Vehicle()
myVehicle.start()Solution
Step 1: Check protocol instantiation
Protocols cannot be instantiated directly, so Vehicle() causes an error.Step 2: Analyze variable assignment
Variable myVehicle must hold an instance of a type conforming to Vehicle, like Car(), not Vehicle() itself.Final Answer:
Cannot instantiate protocol directly with Vehicle() -> Option CQuick Check:
Protocols can't be created with () = Error [OK]
- Trying to create an instance of a protocol
- Confusing protocol with class instantiation
- Ignoring method return types
Animal in an array and calls sound() on each?protocol Animal {
func sound() -> String
}
class Dog: Animal {
func sound() -> String { "Bark" }
}
class Cat: Animal {
func sound() -> String { "Meow" }
}Solution
Step 1: Understand protocol array usage
To store different types conforming to Animal, declare array as [Animal].Step 2: Call method correctly
Use animal.sound() with parentheses to call the method. let animals: [Animal] = [Dog(), Cat()] for animal in animals { print(animal.sound()) } does this correctly.Final Answer:
let animals: [Animal] = [Dog(), Cat()] for animal in animals { print(animal.sound()) } -> Option BQuick Check:
Protocol array with method calls = let animals: [Animal] = [Dog(), Cat()] for animal in animals { print(animal.sound()) } [OK]
- Using concrete type array instead of protocol type
- Calling method without parentheses
- Mixing incompatible types in array
Ready to prove it?
Pass the test and this pattern moves unknown
