Swift
enum inheritance
Swift programming
enums
Swift language features

Swift enum inheritance

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

Introduction

Swift enums are powerful, but they do not support inheritance. You cannot create one enum that extends another enum's cases the way a subclass extends a class, so the practical question is usually not "how do I inherit an enum?" but "what pattern should I use instead?"

Understand the Limitation

This is invalid Swift:

swift
1enum NetworkError {
2    case timeout
3    case offline
4}
5
6enum ApiError: NetworkError {
7    case unauthorized
8}

Enums are value types with a fixed set of cases. Allowing inheritance would break that closed set model, so Swift does not permit it.

Use Protocols for Shared Behavior

If several enums need a common interface, define a protocol and make each enum conform to it.

swift
1protocol DisplayableError {
2    var message: String { get }
3}
4
5enum NetworkError: DisplayableError {
6    case timeout
7    case offline
8
9    var message: String {
10        switch self {
11        case .timeout:
12            return "The request timed out."
13        case .offline:
14            return "No network connection."
15        }
16    }
17}
18
19enum ApiError: DisplayableError {
20    case unauthorized
21    case invalidPayload
22
23    var message: String {
24        switch self {
25        case .unauthorized:
26            return "You are not authorized."
27        case .invalidPayload:
28            return "The server returned invalid data."
29        }
30    }
31}

Now both enums share behavior without inheritance.

Wrap Enums in a Larger Enum When You Need One Type

Sometimes the real goal is to pass several related error types through one API. A wrapper enum is often the cleanest approach.

swift
1enum NetworkError {
2    case timeout
3    case offline
4}
5
6enum ApiError {
7    case unauthorized
8    case invalidPayload
9}
10
11enum AppError {
12    case network(NetworkError)
13    case api(ApiError)
14}
15
16func log(_ error: AppError) {
17    switch error {
18    case .network(.timeout):
19        print("Timed out")
20    case .network(.offline):
21        print("Offline")
22    case .api(.unauthorized):
23        print("Unauthorized")
24    case .api(.invalidPayload):
25        print("Invalid payload")
26    }
27}

This preserves strong typing and keeps the set of possible values explicit.

Use Associated Values for Extensibility

If you want an enum that can represent a family of cases with extra data, associated values often remove the need for inheritance entirely.

swift
1enum PaymentStatus {
2    case pending
3    case failed(code: Int, reason: String)
4    case completed(transactionId: String)
5}
6
7let status = PaymentStatus.failed(code: 402, reason: "Card declined")

Associated values make the enum flexible while still keeping the type self-contained.

Common Pitfalls

The biggest mistake is reaching for a class hierarchy when the problem is really about modeling a fixed set of states. Enums are excellent for closed state machines, and trying to force inheritance onto them usually points to a different design need.

Another issue is overusing wrapper enums when a protocol would be simpler. If you only need shared behavior, protocol conformance is often cleaner than nesting one enum inside another.

Developers also sometimes choose raw values when they really need associated values. Raw values are fine for simple mappings such as status codes, but they do not provide the flexibility that inheritance would have been expected to provide.

Finally, if the set of variants is truly open-ended and expected to grow through third-party extension, an enum may not be the right abstraction at all. A protocol with structs or classes may fit better because it allows external types to participate.

Summary

  • Swift enums do not support inheritance.
  • Use protocols when different enums need shared behavior.
  • Use a wrapper enum when several enum types must flow through one API.
  • Use associated values when cases need extra context or payload data.
  • If the set of cases is not closed, a protocol-based design may be a better fit than an enum.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

All Rights Reserved.