What is a protocol?
A protocol
is a way to require an object to implement a variable, function or init. This allows to identify objects by a protocol, no matter what else they do.
Let's imagine that we have two objects to handle two different type of products, VideoGame
and Computer
. These two products have different properties, but since they need to be scanned, both will have a barcode
property.
struct VideoGame {
var name: String
var genre: String
var barcode: String
}
struct Computer {
var brand: String
var model: String
var barcode: String
}
One of the limitations we have now is that we can't add both product types to the same array.
var re2 = VideoGame(name: "Resident Evil 2", genre: "Horror", barcode: "123")
var re3 = VideoGame(name: "Resident Evil 3", genre: "Horror", barcode: "456")
var macbook = Computer(brand: "Apple", model: "Macbook Pro", barcode: "789")
To solve this we can declare a protocol
that defines barcode
property.
protocol Scanneable {
var barcode: String { get set }
}
Then VideoGame
and Computer
will adopt this protocol (they are already implementing the required barcode
property).
struct VideoGame: Scanneable {
var name: String
var genre: String
var barcode: String
}
struct Computer: Scanneable {
var brand: String
var model: String
var barcode: String
}
Now we can create an array of Scanneable
products.
var products: [Scanneable] = [re2, re3, macbook]
It's important to understand that, for each item in our array, we can only access to the barcode
property, since we are dealing with Scanneable
objects.
print(products[0].barcode)
Add functions and inits
We can also define functions and inits in a protocol. To do this we need to add just the definition of it, without a body, that will be added by each object's implementation.
Let's add the function getDescription
.
protocol Scanneable {
var barcode: String { get set }
func getDescription() -> String
}
Then each model will implement this new function in their own way.
struct VideoGame: Scanneable {
var name: String
var genre: String
var barcode: String
func getDescription() -> String {
"\(name) is a \(genre) game"
}
}
struct Computer: Scanneable {
var brand: String
var model: String
var barcode: String
func getDescription() -> String {
"Buy a \(model) from \(brand)"
}
}
From now, each array item will return a different description according to its product type.
print(products[0].getDescription()) // Resident Evil 2 is a Horror game
print(products[1].getDescription()) // Resident Evil 3 is a Horror game
print(products[2].getDescription()) // Buy a Macbook Pro from Apple
SwiftUI protocols example
Swift is a Protocol-Oriented Programming (POP) language, meaning that we have a wide variety of system protocols.
Let's see an example of how we show a list of objects in our view without using protocols:
struct ContentView: View {
struct Person {
var name: String
}
var people = [
Person(name: "Pablo"),
Person(name: "Andrea"),
Person(name: "Clara"),
Person(name: "Mateo"),
Person(name: "Miguel")
]
var body: some View {
List {
ForEach(0..<people.count, id: \.self) { i in
Text(people[i].name)
}
}
}
}
Now, we are going adopt Identifiable
protocol in our Person
model. This protocol requires to implement a variable named id
. For this example we'll just return the name.
struct ContentView: View {
struct Person: Identifiable {
var id: String {
name
}
var name: String
}
var people = [
Person(name: "Pablo"),
Person(name: "Andrea"),
Person(name: "Clara"),
Person(name: "Mateo"),
Person(name: "Miguel")
]
var body: some View {
List {
ForEach(people) { person in
Text(person.name)
}
}
}
}
Be the first to comment