Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matching enum value in switch when enum implements a protocol

I've got a protocol

protocol P { }

and it's implemented by an enum

enum E: P {
    case a
    case b
}

So far, so good.

I want to be able to receive instances of P, and return a specific value if it's one of E (there will be other enums / structs etc implementing P in the future).

I've tried this:

extension P {

    var value: String {
        switch self {
            case E.a: return "This is an E.a"
            default: return "meh"
        }
    }
}

But this doesn't compile

error: Temp.playground:14:16: error: enum case 'a' is not a member of type 'Self'
    case E.a: return "hello"

I've also tried:

 case is E.a: return "This is an E.a"

which just gives this error:

 error: Temp.playground:14:19: error: enum element 'a' is not a member type of 'E'
     case is E.a: return "hello"
             ~ ^

I know I could do it like this:

switch self {
    case let e as E:
        switch e {
            case E.a: return "hello"
            default: return "meh"
        }
    default: return "meh"
}

but I really really don't want to!

Is there a syntax or technique I'm missing?

like image 827
deanWombourne Avatar asked Feb 08 '18 12:02

deanWombourne


People also ask

Can enum adopt protocol?

Yes, enums can conform protocols.

What is associated value in enum Swift?

In Swift enum, we learned how to define a data type that has a fixed set of related values. However, sometimes we may want to attach additional information to enum values. These additional information attached to enum values are called associated values.

Can you extend an enum Swift?

We can extend the enum in two orthogonal directions: we can add new methods (or computed properties), or we can add new cases. Adding new methods won't break existing code. Adding a new case, however, will break any switch statement that doesn't have a default case.


2 Answers

You need to match against type E before you can test against the value E.a, but this can be done in a single expression:

extension P {    
    var value: String? {
        switch self {
        case let e as E where e == .a:
            return "hello"
        default:
            return nil
        }
    }
}
like image 147
Martin R Avatar answered Nov 15 '22 06:11

Martin R


You can define your P extension with specific type enum in your case

create extension like this

extension P where Self == E {
    var value:String {
        switch self  {
        case .a  :
                return "A"
        case .b:
            return "b"

        }
    }
}

let e = E.a.value
print(e)

Output :

"A"

like image 26
Prashant Tukadiya Avatar answered Nov 15 '22 07:11

Prashant Tukadiya