Search code examples
swiftenumssolid-principlesliskov-substitution-principle

Does using enum with associated value in Swift violate Liskov Substitution Principle?


enum WeatherType {
    case cloudy(coverage: Int)
    case sunny
    case windy
}

I just saw this in a Swift tutorial and I can't believe they allow you to do that. Now, whenever I switch on that enum, I gotta create a special case for cloudy!


Solution

  • You don't "gotta" do anything. If you don't care what the coverage is, don't ask what the coverage is. If you don't care if it's cloudy, don't ask if it's cloudy. There is nothing special about the way you write a switch for a case that has an associated value.

    Suppose we have this:

    let weather = WeatherType.cloudy(coverage:1)
    

    Then this is perfectly legal:

    switch weather {
    case .sunny:
        print("it is sunny")
    default:
        print("I guess it's cloudy, or maybe windy")
    }
    

    And so is this!

    switch weather {
    case .cloudy:
        print("it is cloudy")
    default:
        print("I guess it's sunny, or maybe windy")
    }
    

    Nor does any law require you to write a switch statement at all. If you simply want to know whether weather is .cloudy, just ask:

    if case .cloudy = weather {
        print("yes it is cloudy")
    } else {
        print("I guess it's sunny, or maybe windy")
    }
    

    And if you do happen to want to know what the coverage is, you still don't have to write a switch statement:

    if case let .cloudy(cov) = weather {
        print("yes it is cloudy, in fact it is \(cov)")
    } else {
        print("I guess it's sunny, or maybe windy")
    }
    

    What you cannot do is apply ==. This won't compile:

    if weather == .sunny { // error
    

    To that extent, yes, an enum with an associated value behaves differently from an enum without an associated value (if that's what you're asking).