Menu
Coddy logo textTech

Defining Protocols

Part of the Object Oriented Programming section of Coddy's Swift journey. Lesson 27 of 57.

A protocol lists requirements (methods and properties) without implementing them. A type conforms to the protocol by providing every requirement, and then it can be used wherever the protocol is expected:

protocol Describable {
    func describe() -> String
}

struct Book: Describable {
    let title: String
    func describe() -> String { "Book: \(title)" }
}

print(Book(title: "Dune").describe())

Output:

Book: Dune

Unlike inheritance, a protocol works for structs, classes and enums alike, and a type can conform to many protocols. The protocol only says what a type can do; each type decides how:

protocol Describable {
    func describe() -> String
}

struct Point: Describable {
    var x = 0, y = 0
    func describe() -> String { "(\(x), \(y))" }
}

enum Level: Describable {
    case low, high
    func describe() -> String { self == .low ? "low" : "high" }
}

print(Point(x: 1, y: 2).describe())
print(Level.high.describe())

Output:

(1, 2)
high

Property requirements state the type and whether the property is read-only ({ get }) or also writable ({ get set }). A { get } requirement can be met by a stored or a computed property:

protocol Named {
    var name: String { get }
}

struct User: Named {
    let name: String
}

struct Planet: Named {
    var number: Int
    var name: String { "Planet \(number)" }
}

print(User(name: "ada").name)
print(Planet(number: 3).name)

Output:

ada
Planet 3

If a type claims to conform but misses a requirement, it does not compile. The compiler checks every conformance, so code that uses the protocol can rely on it:

protocol Priced {
    var price: Int { get }
    func discounted(by percent: Int) -> Int
}

// struct Ticket: Priced { var price = 10 }
// error: type 'Ticket' does not conform to protocol 'Priced'
challenge icon

Challenge

Easy

Declare a protocol Shape with a read-only property name (String) and a method area() returning Double. Make the structs Rectangle (width, height) and Circle (radius, using 3.0 for π to keep the numbers simple) conform to it, with the names rectangle and circle.

The supplied code reads lines r,3,4 or c,2, creates the matching shape and prints rectangle: 12.0.

Your code goes in Shape.swift, Rectangle.swift and Circle.swift. main.swift holds the supplied input/output code and cannot be edited.

Try it yourself

// Supplied input/output code: keep it as it is
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
    let p = line.split(separator: ",").map(String.init)
    if p[0] == "r" {
        let s = Rectangle(width: Double(p[1])!, height: Double(p[2])!)
        print("\(s.name): \(s.area())")
    } else {
        let s = Circle(radius: Double(p[1])!)
        print("\(s.name): \(s.area())")
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Swift playground