Protocol composition in practice in Swift - Time & Space Complexity
When using protocol composition in Swift, it is important to understand how the program's work grows as input changes.
We want to know how combining multiple protocols affects the time it takes to run code that uses them.
Analyze the time complexity of the following code snippet.
protocol A {
func doA()
}
protocol B {
func doB()
}
func performAction(item: A & B) {
item.doA()
item.doB()
}
This code defines two protocols and a function that takes an item conforming to both. It calls methods from both protocols.
Look for repeated work inside the function when called with different inputs.
- Primary operation: Calling two methods on the item.
- How many times: Each method is called once per function call.
The function calls two methods regardless of input size. If the methods themselves do not loop, the work stays the same.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 2 |
| 100 | 2 |
| 1000 | 2 |
Pattern observation: The total work stays constant regardless of input size.
Time Complexity: O(1)
This means the time to run stays constant regardless of input size.
[X] Wrong: "Using protocol composition makes the function slower because it combines protocols."
[OK] Correct: Protocol composition itself does not add extra loops or repeated work; it just requires the item to meet multiple requirements.
Understanding how protocol composition affects performance helps you write clear and efficient Swift code, a useful skill in many coding situations.
"What if the methods doA() and doB() each contained loops over the input? How would that change the time complexity?"
Practice
Solution
Step 1: Understand protocol composition concept
Protocol composition uses the & operator to require multiple protocols at once without defining a new protocol.Step 2: Compare options with concept
Only Combine multiple protocols into one requirement without creating a new protocol correctly describes combining multiple protocols without creating a new one. Other options describe unrelated or incorrect Swift features.Final Answer:
Combine multiple protocols into one requirement without creating a new protocol -> Option AQuick Check:
Protocol composition = Combine protocols [OK]
- Confusing protocol composition with class inheritance
- Thinking protocols can have stored properties
- Believing protocol extensions override methods
Codable and Equatable protocols using protocol composition?Solution
Step 1: Recall protocol composition syntax
Swift uses & to combine protocols in type requirements, likeCodable & Equatable.Step 2: Evaluate each option
func save(item: Codable & Equatable) {} uses correct & syntax. func save(item: Codable | Equatable) {} uses | which is invalid. func save(item: Codable, Equatable) {} uses comma which is invalid. func save(item: Codable && Equatable) {} uses && which is invalid.Final Answer:
func save(item: Codable & Equatable) {} -> Option BQuick Check:
Use & to combine protocols [OK]
- Using | or && instead of & for protocol composition
- Separating protocols with commas in parameter types
- Confusing logical operators with protocol composition
protocol A { func foo() }
protocol B { func bar() }
struct MyStruct: A, B {
func foo() { print("foo") }
func bar() { print("bar") }
}
func callBoth(item: A & B) {
item.foo()
item.bar()
}
let obj = MyStruct()
callBoth(item: obj)Solution
Step 1: Understand protocol composition usage
The functioncallBothrequires an argument conforming to bothAandB.MyStructconforms to both.Step 2: Trace function calls
InsidecallBoth,foo()prints "foo" andbar()prints "bar". Both are called in order.Final Answer:
foo bar -> Option AQuick Check:
Both protocol methods called = foo\nbar [OK]
- Assuming only one protocol method runs
- Expecting a compile error due to protocol composition
- Confusing protocol conformance with inheritance
protocol P1 { func p1Method() }
protocol P2 { func p2Method() }
func testFunc(param: P1 & P2) {
param.p1Method()
param.p2Method()
}
struct S: P1 {
func p1Method() { print("P1") }
}
let s = S()
testFunc(param: s)Solution
Step 1: Check struct conformance
StructSconforms only toP1, missingP2conformance.Step 2: Analyze function parameter requirement
FunctiontestFuncrequires a parameter conforming to bothP1andP2. Passingsfails becauseslacksP2.Final Answer:
Struct S does not conform to protocol P2 -> Option DQuick Check:
Missing protocol conformance causes error [OK]
- Assuming partial protocol conformance is enough
- Thinking function parameter syntax is incorrect
- Believing protocols cannot be combined with &
protocol Drawable { func draw() }
protocol Colorable { var color: String { get } }
struct Circle: Drawable, Colorable {
var color: String
func draw() { print("Drawing a circle") }
}
struct Square: Drawable {
func draw() { print("Drawing a square") }
}Which of the following function signatures correctly accepts only objects that are both
Drawable and Colorable?Solution
Step 1: Understand protocol composition for parameters
To accept only objects conforming to bothDrawableandColorable, useDrawable & Colorable.Step 2: Check each function signature
func render(item: Drawable & Colorable) { item.draw(); print(item.color) } uses correct composition and accesses bothdraw()andcolor. Options A, B, and D either use invalid syntax or accept only one protocol.Final Answer:
func render(item: Drawable & Colorable) { item.draw(); print(item.color) } -> Option CQuick Check:
Use & to require multiple protocols [OK]
- Using | instead of & for protocol composition
- Accepting only one protocol when both are needed
- Trying to access properties/methods not guaranteed by parameter type
Ready to prove it?
Pass the test and this pattern moves unknown
