📖 Scenario: Imagine you are building a simple app that manages different types of vehicles. Each vehicle can have different capabilities like driving, flying, or floating on water. You want to organize these capabilities using protocols and combine them to create specific vehicle types.
🎯 Goal: You will create protocols for different vehicle capabilities, then use protocol composition to define specific vehicle types that combine these capabilities. Finally, you will create instances of these vehicles and demonstrate their abilities.
📋 What You'll Learn
Create protocols named Drivable, Flyable, and Floatable each with one method signature.
Create a struct named Car that conforms to Drivable.
Create a struct named AmphibiousCar that conforms to both Drivable and Floatable using protocol composition.
Create a struct named FlyingCar that conforms to Drivable and Flyable using protocol composition.
Write a function that accepts a parameter conforming to both Drivable and Flyable and calls their methods.
Print outputs demonstrating the capabilities of each vehicle.
💡 Why This Matters
🌍 Real World
Protocol composition is useful when you want to build flexible and reusable code that models real-world objects with multiple capabilities, like vehicles that can drive, fly, or float.
💼 Career
Understanding protocol composition is important for Swift developers working on apps that require clean architecture and modular design, such as games, simulations, or complex user interfaces.
Progress0 / 4 steps
1
Create protocols for vehicle capabilities
Create three protocols named Drivable, Flyable, and Floatable. Each protocol should have one method signature: drive() for Drivable, fly() for Flyable, and float() for Floatable.
Swift
Hint
Protocols define methods without implementation. Use protocol keyword and declare one method per protocol.
2
Create a Car struct conforming to Drivable
Create a struct named Car that conforms to the Drivable protocol. Implement the drive() method to print "Car is driving".
Swift
Hint
Use struct Car: Drivable and implement drive() with a print statement.
3
Create AmphibiousCar and FlyingCar with protocol composition
Create a struct named AmphibiousCar that conforms to both Drivable and Floatable. Implement drive() to print "AmphibiousCar is driving" and float() to print "AmphibiousCar is floating". Then create a struct named FlyingCar that conforms to Drivable and Flyable. Implement drive() to print "FlyingCar is driving" and fly() to print "FlyingCar is flying".
Swift
Hint
Use commas to conform to multiple protocols. Implement all required methods with print statements.
4
Use protocol composition in a function and print outputs
Write a function named testDriveAndFly that accepts one parameter named vehicle of type Drivable & Flyable. Inside the function, call drive() and fly() on vehicle. Then create instances of Car, AmphibiousCar, and FlyingCar. Call drive() on Car and AmphibiousCar, call float() on AmphibiousCar, and call testDriveAndFly with the FlyingCar instance.
Swift
Hint
Use Drivable & Flyable as the parameter type. Call methods on instances to see printed messages.
Practice
(1/5)
1. What does protocol composition in Swift allow you to do?
easy
A. Combine multiple protocols into one requirement without creating a new protocol
B. Create a new class that inherits from multiple classes
C. Define a protocol with stored properties
D. Override methods in a protocol extension
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 A
Quick Check:
Protocol composition = Combine protocols [OK]
Hint: Remember & means combine protocols, not inherit classes [OK]
Common Mistakes:
Confusing protocol composition with class inheritance
Thinking protocols can have stored properties
Believing protocol extensions override methods
2. Which of the following is the correct syntax to declare a function parameter that requires both Codable and Equatable protocols using protocol composition?
easy
A. func save(item: Codable | Equatable) {}
B. func save(item: Codable & Equatable) {}
C. func save(item: Codable, Equatable) {}
D. func save(item: Codable && Equatable) {}
Solution
Step 1: Recall protocol composition syntax
Swift uses & to combine protocols in type requirements, like Codable & 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 B
Quick Check:
Use & to combine protocols [OK]
Hint: Use & to combine protocols, not |, comma, or && [OK]
Common Mistakes:
Using | or && instead of & for protocol composition
Separating protocols with commas in parameter types
Confusing logical operators with protocol composition
3. What will be the output of the following Swift code?
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)
medium
A. foo\nbar
B. foo
C. bar
D. Compilation error
Solution
Step 1: Understand protocol composition usage
The function callBoth requires an argument conforming to both A and B. MyStruct conforms to both.
Step 2: Trace function calls
Inside callBoth, foo() prints "foo" and bar() prints "bar". Both are called in order.
Final Answer:
foo
bar -> Option A
Quick Check:
Both protocol methods called = foo\nbar [OK]
Hint: Both protocols' methods run in order when composed [OK]
Common Mistakes:
Assuming only one protocol method runs
Expecting a compile error due to protocol composition
Confusing protocol conformance with inheritance
4. Identify the error in this Swift code using protocol composition:
Struct S conforms only to P1, missing P2 conformance.
Step 2: Analyze function parameter requirement
Function testFunc requires a parameter conforming to both P1 and P2. Passing s fails because s lacks P2.
Final Answer:
Struct S does not conform to protocol P2 -> Option D
Quick Check:
Missing protocol conformance causes error [OK]
Hint: Check all protocols are conformed before passing composed type [OK]
Common Mistakes:
Assuming partial protocol conformance is enough
Thinking function parameter syntax is incorrect
Believing protocols cannot be combined with &
5. Given these protocols and structs:
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?
hard
A. func render(item: Drawable) { item.draw() }
B. func render(item: Drawable | Colorable) { item.draw() }
C. func render(item: Drawable & Colorable) { item.draw(); print(item.color) }
D. func render(item: Colorable) { print(item.color) }
Solution
Step 1: Understand protocol composition for parameters
To accept only objects conforming to both Drawable and Colorable, use Drawable & Colorable.
Step 2: Check each function signature
func render(item: Drawable & Colorable) { item.draw(); print(item.color) } uses correct composition and accesses both draw() and color. Options A, B, and D either use invalid syntax or accept only one protocol.