Menu
Coddy logo textTech

Polymorphism

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

Polymorphism means one piece of code works with values of many types, and each value responds in its own way. The loop below calls sound() without knowing which animal it holds:

class Animal {
    func sound() -> String { "..." }
}
class Dog: Animal {
    override func sound() -> String { "Woof" }
}
class Cow: Animal {
    override func sound() -> String { "Moo" }
}

let farm: [Animal] = [Dog(), Cow(), Dog()]
for a in farm { print(a.sound()) }

Output:

Woof
Moo
Woof

Swift decides which implementation to run at run time, from the actual object. The variable's declared type does not matter; the object's type does:

class Animal {
    func sound() -> String { "..." }
}
class Cat: Animal {
    override func sound() -> String { "Meow" }
}

let pet: Animal = Cat()
print(pet.sound())

Output:

Meow

Protocols give the same flexibility to structs and enums. Here one function prints any list of Drawable values:

protocol Drawable {
    func draw() -> String
}
struct Line: Drawable {
    let length: Int
    func draw() -> String { String(repeating: "-", count: length) }
}
struct Box: Drawable {
    func draw() -> String { "[ ]" }
}

func render(_ items: [any Drawable]) -> String {
    items.map { $0.draw() }.joined(separator: " ")
}

print(render([Line(length: 3), Box(), Line(length: 1)]))

Output:

--- [ ] -

Polymorphism replaces long if/switch chains over kinds of things. Instead of asking what a value is and then deciding what to do, you ask the value to do it. Adding a new kind means adding a new type, not editing every switch:

// without polymorphism
if kind == "dog" { print("Woof") } else if kind == "cow" { print("Moo") }

// with polymorphism
for animal in farm { print(animal.sound()) }
challenge icon

Challenge

Easy

Animal has name, legs() (4) and describe(), which returns Rex has 4 legs and says Woof, built from legs() and sound(). Declare Dog (sound Woof), Bird (2 legs, sound Tweet) and Snake (0 legs, sound Hiss) by overriding only legs() and sound().

The supplied code reads lines dog,Rex, bird,Pip or snake,Kaa, stores the animals in one [Animal] array and prints describe() for each.

Your code goes in Animal.swift, Dog.swift, Bird.swift and Snake.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) }
var zoo: [Animal] = []
for line in input {
    let p = line.split(separator: ",").map(String.init)
    switch p[0] {
    case "dog": zoo.append(Dog(name: p[1]))
    case "bird": zoo.append(Bird(name: p[1]))
    default: zoo.append(Snake(name: p[1]))
    }
}
for a in zoo { print(a.describe()) }
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