Swift Defining Protocols
A protocol is a list of requirements that a type can promise to meet. A type that provides everything on the list conforms to the protocol.
One type conforms
The Named protocol requires a name property and a label method. The Person struct declares Named and supplies both parts.
protocol Named {
var name: String { get }
func label() -> String
}
struct Person: Named {
var name: String
func label() -> String {
return "Name: \(name)"
}
}
let person = Person(name: "Ana")
print(person.name)
print(person.label())Two types conform
Cheetah and Tortoise both declare the Runner protocol. Each supplies its own speed value and its own run method.
protocol Runner {
var speed: Int { get }
func run() -> String
}
struct Cheetah: Runner {
var speed: Int
func run() -> String {
return "Cheetah runs at \(speed)"
}
}
struct Tortoise: Runner {
var speed: Int
func run() -> String {
return "Tortoise walks at \(speed)"
}
}
let cheetah = Cheetah(speed: 60)
let tortoise = Tortoise(speed: 1)
print(cheetah.run())
print(tortoise.run())A function accepts the protocol
The show function takes any Named value as its parameter. It prints the label of a Book struct and a Song class with the same call shape.
protocol Named {
var name: String { get }
func label() -> String
}
struct Book: Named {
var name: String
func label() -> String {
return "Book: \(name)"
}
}
class Song: Named {
var name: String
init(name: String) {
self.name = name
}
func label() -> String {
return "Song: \(name)"
}
}
func show(_ item: Named) {
print(item.label())
}
let book = Book(name: "Dune")
let song = Song(name: "Blue")
show(book)
show(song)Example
protocol Priced {
var price: Int { get }
func priceTag() -> String
}
struct Ticket: Priced {
var price: Int
func priceTag() -> String {
return "Ticket costs \(price)"
}
}
class Pass: Priced {
var price: Int
init(price: Int) {
self.price = price
}
func priceTag() -> String {
return "Pass costs \(price)"
}
}
func printTag(_ item: Priced) {
print(item.priceTag())
}
let ticket = Ticket(price: 12)
let pass = Pass(price: 40)
printTag(ticket)
printTag(pass)
print(ticket.price + pass.price)Key points
- The protocol keyword starts a protocol definition.
- A property requirement names a property, its type, and how it can be accessed.
- The { get } mark means a conforming property must at least be readable.
- A method requirement gives a name and a return type, but no body.
- A conforming type declares the protocol after a colon in its own declaration.
- A conforming type supplies its own property values and method bodies.
- A function can accept a protocol type and work with any conforming type.
In this example, the Priced protocol requires a price property and a priceTag method. The Ticket struct and the Pass class both conform in their own declarations. The printTag function accepts the Priced type, so one function prints both tags, and the last print adds the two prices and shows 52.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does the { get } mark on a protocol property requirement mean?