Swift enum inheritance

56,654

Solution 1

In Swift language, we have Structs, Enum and Classes. Struct and Enum are passed by copy but Classes are passed by reference. Only Classes support inheritance, Enum and Struct don't.

So to answer your question, you can't have inheritance with Enum (and Struct types). Have a look here:

stackOverflow difference classes vs structs

Solution 2

As Korpel answered already, currently there is no actual inheritance supported for Enums. So it is not possible to have a certain Enum extend and inherit the cases of another enum.

However, I would add for completion, that Enums do support protocols, and together with protocol extensions introduced in Swift 2 and the new protocol-oriented programming approach (see this video), it is possible to implement something that resembles inheritance. This is a technique I use a lot to define UITableViewController:s driven by enums, to specify the sections of the table, and the rows within each section, and to add some useful behaviour. See for example the following sample code:

import UIKit

protocol TableSection {
    static var rows: [Self] { get }

    var title: String { get }

    var mandatoryField: Bool { get }
}

extension TableSection {
    var mandatoryTitle: String {
        if mandatoryField {
            return "\(title)*"
        } else {
            return title
        }
    }
}

enum RegisterTableSection: Int, TableSection {
    case Username
    case Birthdate
    case Password
    case RepeatPassword

    static var rows: [RegisterTableSection] {
        return [.Username, .Password, .RepeatPassword]
    }

    var title: String {
        switch self {
        case .Username:
            return "Username"
        case .Birthdate:
            return "Date of birth"
        case .Password:
            return "Password"
        case .RepeatPassword:
            return "Repeat password"
        }
    }

    var mandatoryField: Bool {
        switch self {
        case .Username:
            return true
        case .Birthdate:
            return false
        case .Password:
            return true
        case .RepeatPassword:
            return true
        }
    }
}

class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return RegisterTableSection.rows.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        guard let row = RegisterTableSection(rawValue: indexPath.row) else {
            // This should never happen
            return UITableViewCell()
        }

        let cell = UITableViewCell()
        cell.textLabel?.text = row.mandatoryTitle
        return cell

    }
}

The previous code would render the following table:

Enum-defined table

Notice how by implementing the protocol, our RegisterTableSection enum has to provide implementations to methods and variables defined in the protocol. And most interestingly, it inherits a default implementation of the variable mandatoryTitle through the TableSection protocol extension

I have uploaded the source code of this example here

Solution 3

Look at my example, it is much easier: Can an enum contain another enum values in Swift?

Details

Tested on:

  • Xcode 9.2, Swift 4 and 3
  • Xcode 10.2 (10E125) and 11.0 (11A420a), Swift 5

Solution

enum State {
    case started
    case succeeded
    case failed
}

enum ActionState {
    case state(value: State)
    case cancelled
}

Result

ActionState enum has 4 values:

.state(value: .started)
.state(value: .succeeded)
.state(value: .failed)
.cancelled

Another sample

import Foundation

enum StringCharactersTransformType {
    case upperCase
    case lowerCase
}

enum StringTransformType {
    case state(value: StringCharactersTransformType)
    case normal

    static var upperCase: StringTransformType {
        return .state(value: .upperCase)
    }

    static var lowerCase: StringTransformType {
        return .state(value: .lowerCase)
    }
}

var type = StringTransformType.normal
print(type)
type = .upperCase
print(type)
type = .lowerCase
print(type)

Result

enter image description here enter image description here

Share:
56,654
Boon
Author by

Boon

I manage a team that builds highly-innovative interactive apps and games for mobile and web. I love building things that reach a lot of people make people happy

Updated on July 05, 2022

Comments

  • Boon
    Boon almost 2 years

    Can you inherit enum in Swift? What are the rules that one should be aware of with regards to enum inheritance?

    The following test code:

    enum TemperatureUnit: Int {
        case Kelvin, Celcius, Farenheit
    }
    
    enum TemperatureSubunit : Temperature {  
    }
    

    generates

    error: type 'TemperatureSubunit' does not conform to protocol 'RawRepresentable'
    
  • SomaMan
    SomaMan almost 8 years
    This is an excellent answer, and shows another bonus of protocol-orientated programming
  • Warpzit
    Warpzit almost 8 years
    Amazing fail but so be it. Thanks for info.
  • Sentry.co
    Sentry.co over 7 years
    I like it. But the idea of Enum is that you can infer constants. like: someFunction("hello world",.upperCase) someFunction("hello world",.lowerCase) etc. This: someFunction("hello world",.state(.upperCase))is not very readable? Nice idea though.
  • Vasily  Bodnarchuk
    Vasily Bodnarchuk over 7 years
    Yes you are right. I have edited the answer (added a example of the beautiful code). That's better?
  • Sentry.co
    Sentry.co over 7 years
    It's sort of reverse inheritance though. This is more like Composition. If you think about it. In my opinion enums work well with protocol oriented programming and less so with OOP and inheritance. Luckily swift still support both OOP and POP. For now.
  • Nuno Gonçalves
    Nuno Gonçalves almost 7 years
    Great idea! Enum composition!
  • Segabond
    Segabond almost 7 years
    Yeah it actually solves the problem of being unable to extend Error enums coming from 3rd party frameworks. Composition is exactly what I needed!
  • Korpel
    Korpel almost 7 years
    excelent answer Luis!
  • Reimond Hill
    Reimond Hill almost 6 years
    Actually your idea inspired me for my problem!