Start learning free

LESSON 409 OF 415 · OBJECT-ORIENTED PROGRAMMING

Interfaces in Swift: Protocols and Conformance

Lesson Read the full explanation

TL ; DR:

An interface (a protocol in Swift) is a pure contract — a list of methods that a class promises to implement, with no shared data and no shared code. Unlike inheritance ("is a"), interfaces express "can do".


protocol Speaker {
    func speak()
}
class Dog: Speaker {
    func speak() {
        print("Woof")
    }
}


Full lesson:

An interface defines what a class can do, not how it does it or what it is. A Truck, a Robot, and a Drone aren't the same kind of thing — but they can all move(). You'd put move() in a Movable protocol and have each one adopt it.

Interface vs abstract class

Abstract classInterface
Has fieldsYesNo stored fields (a protocol can only require properties)
Has method bodiesYes (some)No (default implementations only through a protocol extension)
Multiple "inheritance"Usually noYes — a class can adopt many protocols
Models"is a""can do"

A class inherits from at most one parent class but can adopt many protocols. That's why protocols are the right tool for cross-cutting capabilities like Comparable, Equatable, Codable, Sequence, etc.

The language landscape

  • Swift — the keyword is protocol. A class lists the protocols it adopts after its name (and after its superclass, if it has one), separated by commas; structs and enums can adopt protocols too.
  • C# / Java — first-class interface keyword. C# uses : for both inheritance and implementation; Java uses extends for inheritance and implements for interfaces.
  • Python — no separate interface; abstract base classes (ABCs) with all-abstract methods serve the same role.
  • JavaScript — no interface keyword in plain JS (TypeScript has it). The convention is a stub class.
  • C++ — a class with only pure-virtual methods is an interface. Multiple inheritance lets a class implement several.

Your task

The Speaker protocol is already declared. Create a Dog class that adopts it, with a speak() method that prints "Woof".

Expected output:

Woof
STEP 1 OF 2
    Ctrl + Enter to check

    SWIFT · OBJECT-ORIENTED PROGRAMMING

    Interfaces in Swift, explained

    What an interface is

    An interface is a contract: a list of things a type promises to do, with no say in how. A Truck, a Robot and a Drone are different kinds of thing, but all of them can move. A "can move" contract lets code that only needs movement work with all three.

    Where inheritance models "is a" (a Dog is an Animal), an interface models "can do". Swift's name for an interface is a protocol.

    Declaring and adopting a protocol

    A protocol lists requirements and gives no bodies:

    protocol Speaker {
        func speak()
    }
    

    A type adopts the protocol by naming it after a colon, and then implements every requirement:

    class Dog: Speaker {
        func speak() {
            print("Woof")
        }
    }
    

    Two points set this apart from inheritance. The implementation needs no override, because there is no parent body to replace. And the check is made by the compiler. If Dog adopts Speaker and has no speak(), the code does not compile. The error reads type 'Dog' does not conform to protocol 'Speaker', with a note that the protocol requires speak().

    Using the protocol as a type

    A protocol name can be the type of a variable, a parameter or an array element. The code then knows only what the protocol promises:

    let rex: Speaker = Dog()
    rex.speak()
    

    This is polymorphism through a contract: the call reaches whichever type is behind rex. It lets unrelated types share one array:

    struct Robot: Speaker {
        func speak() { print("Beep") }
    }
    
    let things: [Speaker] = [Dog(), Robot()]
    for t in things { t.speak() }
    
    Woof
    Beep
    

    Dog is a class and Robot is a struct, and they have no common parent. The protocol is the only thing they share.

    A protocol cannot be created on its own. Speaker() is a compile error, since a protocol has no implementation to build.

    Many protocols, one parent

    A class has at most one superclass but can adopt any number of protocols. List them after the colon, separated by commas. If the class has a superclass, the superclass goes first. Here Mover is a protocol with a single move() requirement:

    class Puppy: Dog, Mover {
        func move() { print("bounding") }
    }
    

    This is why protocols suit capabilities that cut across hierarchies, such as comparing or hashing. The standard library's Comparable and Hashable are protocols.

    Default implementations

    An extension on a protocol can supply a body for a requirement, and types that adopt the protocol then get it for free:

    protocol Mover {
        func move()
    }
    
    extension Mover {
        func move() { print("moving") }
    }
    
    struct Robot: Mover {
        func move() { print("rolling") }
    }
    

    A type that adopts Mover without writing move() prints moving. Robot writes its own and prints rolling. Because move() is a requirement of the protocol, a call through a Mover variable uses the type's own version. A method that exists only in the extension and is not a requirement is chosen from the variable's declared type, so a type's own method with the same name is ignored in that case.

    Interface or abstract class

    Class with a baseProtocol
    Stored propertiesYesNo, only property requirements
    Method bodiesYesOnly through extensions
    Who can adopt itSubclasses of a classClasses, structs and enums
    How manyOne superclassAny number
    Models"is a""can do"

    The lesson's exercise

    The starter code declares the Speaker protocol and a Solution class that builds a Dog and calls speak(). The Dog class is missing, and the output must be Woof.

    1. Declare Dog and adopt Speaker. Write class Dog: Speaker below the protocol. The colon is the same one used for a superclass, and no superclass is involved here.
    2. Implement speak. Add func speak() that prints Woof. A protocol requirement without a body in the type makes the class fail to compile, and no override keyword is used.
    protocol Speaker {
        func speak()
    }
    
    class Dog: Speaker {
        func speak() {
            print("Woof")
        }
    }
    
    class Solution {
        func mainFunction() {
            let rex: Speaker = Dog()
            rex.speak()
        }
    }
    

    The method name and signature must match the requirement exactly. A func speak(loudly: Bool) would be a different method and would not satisfy it.

    Key takeaways

    • A Swift interface is a protocol: a list of requirements with no stored data.
    • Adopt one with : ProtocolName and implement every requirement, without override.
    • The compiler rejects a type that leaves a requirement out.
    • A type can adopt many protocols, with the superclass first if there is one.
    • Protocols work for structs and enums as well as classes.
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free