2015-11-12 15 views
31

Zauważam dziwne, szybkie zachowanie, ponieważ moim zdaniem zmienna kolorów nie powinna być rozpakowywana w przypadku zmiany przełącznika poniżej, ale bez rozpakowania kompilator pokazuje mi komunikat o błędzie.Dlaczego wymuszenie rozpakowania jest wymagane w przypadku wyliczenia i zmiany?

enum Colours: Int { 
case Red = 0, White, Black 
} 

var colours: Colours! 
colours = .Red 

switch colours! { // <-- why I have to unwrap colours? As you can see colours are declared as '!' 
case .Red: break 
default: break 
} 

jeśli zmienna nie jest rozpakowany kolory kompilator pokazuje mi ten błąd: enter image description here

moim zdaniem to jest SWIFT niekonsekwencja, czy ktoś ma jakieś pomysły?

Odpowiedz

32

Przy zastosowaniu w switch oświadczenia, nawet w sposób dorozumiany odwinął OPCJE są nie automatycznie rozpakowany. (A powodem może być to, że nie mógł dopasować je przed nil inaczej).

Więc trzeba rozpakować (albo przymusowo z colours! który padnie jeśli colours == nil lub z opcjonalnym wiązania), lub - alternatywnie - mecz przeciwko .Red? która jest skrótem dla .Some(.Red):

var colours: Colours! 

switch colours { 
case .Red?: 
    break // colours is .Red 
default: 
    break // colours is .White, .Black or nil 
} 

to samo dotyczy innych określeń pasujących do wzorca, np

if case .Red? = colours { 
    // colours is .Red 
} else { 
    // colours is .White, .Black or nil 
} 

Również w tym nie ma nic wspólnego z typów wyliczeniowych, tylko z niejawnie nieopakowanych optionals we wzorze:

let x : Int! = 1 

switch x { 
case nil: 
    break // x is nil 
case 1?: 
    break // x is 1 
default: 
    break // x is some other number 
} 
+0

Kilka z twoich "kolorów" to "kolory" ;-) – vacawama

+0

@vacawama: Obwiniaj autokorektę :) –

+0

Tak! Autokorekta poprawiała również mój komentarz. Ta wina naprawdę może należeć do Noah Webster. :-) – vacawama

2

Dzieje się tak, ponieważ tworzysz zmienną colours jak typ opcjonalny. Jeśli zrobisz tak:

var colours: Colours 
colours = .Red 

nie będzie musiał unwrappe tę wartość

Jeśli spojrzymy na to, co opcjonalny typ jest, widzimy, że jest to enum jak:

enum Optional<T> { 
    case Some(T) 
    case None 
} 

Może to być np. Some Wpisz na przykład Int lub None iw tym przypadku ma wartość zerową.

Po dokonaniu tego:

var colours: Colours! 

bezpośrednio jest wskazywany przez ! że to nie jest Colours typ ale jest to rodzaj enum ImplicitlyUnwrappedOptional<Colours>. W momencie tworzenia będzie to Some<Colours>, jeśli będzie równa tej wartości, ale z tym ! masz to, że jest enum ImplicitlyUnwrappedOptional<Colours>, aw najbliższej chwili będzie to None. Dlatego trzeba użyć ! w switch:

Twoja wartość colours jest ImplicitlyUnwrappedOptional<Colours> typu i może być Colours lub nil i trzeba bezpośrednio wskazują, że ten typ jest Colours w `switch``.

+1

mógł Pan podać jakąś dokumentację wykazującą, że deklarując zmienną '' sprawia, że ​​opcja ? – Arc676

+0

@ Arc676 i edytuj odpowiedź –

+1

'colors' ma typ' ImplicitlyUnwrappedOptional '', a nie 'Opcjonalny '. –

1

Zamiast:

var colours: Colours! 
colours = .Red 

Wystarczy użyć

var colours = Colours.Red 

To powinno załatwić sprawę.

+1

Ale chcę mieć opcjonalną zmienną kolorów. Powinno działać bez "!" w mojej opinii. – Robert

+2

@roher Deklarowanie zmiennej typu wyliczeniowego jako opcjonalnego nie jest zbyt użyteczne, ponieważ wyliczenie ma określony stan. Użyj stanu .None lub podobnego zamiast opcjonalnego. – vadian

Powiązane problemy