W Rust enumy mogą przechowywać nie tylko wartości (warianty), ale także skojarzone z nimi dane (ładunek). Czyni to je szczególnie wygodnymi do tworzenia algebraicznych typów danych, na przykład do reprezentacji stanu lub wiadomości z parametrami. Na przykład:
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }
Do obsługi takich enumów zazwyczaj używa się operatora match, który pozwala wypakować zagnieżdżone wartości każdego wariantu:
let msg = Message::Move { x: 10, y: 20 }; match msg { Message::Quit => println!("Wiadomość Quit"), Message::Move { x, y } => println!("Ruch do ({}, {})", x, y), Message::Write(text) => println!("Tekst: {}", text), Message::ChangeColor(r, g, b) => println!("Zmiana koloru na ({}, {}, {})", r, g, b), }
Takie podejście pozwala na bezpieczne i wyraźne obsługiwanie wszystkich możliwych przypadków, co minimalizuje błędy w logice programu.
Dlaczego w Rust nie ma null dla enumów, i co zwróci próba dopasowania do nieistniejącego wariantu?
Częsty błędny odpowiedź: "Kompilator zignoruje błąd, jeśli nie obsłuży się wszystkich wariantów enum w match."
W rzeczywistości kompilator zgłosi błąd, jeśli nie zostaną uwzględnione wszystkie możliwe warianty, lub zażąda dodania catch-all (_). Na przykład:
enum Status { Ok, Err(String) } let st = Status::Ok; match st { Status::Ok => println!("Ok"), // Jeśli zapomnimy o Status::Err, kompilator narzeka }
Historia W jednym projekcie podczas rozszerzania enumu nie dodano obsługi nowego wariantu w match we wszystkich miejscach, gdzie był używany. Doprowadziło to do panic! w wersji, ponieważ
matchnie był wyczerpujący (exhaustive), a testy nie obejmowały wszystkich przypadków.
Historia W innym przypadku próbowano porównać enum za pomocą zwykłego
==bez implementacji PartialEq dla złożonych wariantów z danymi skojarzonymi, co spowodowało niespodziewany błąd kompilacji.
Historia Zespół użył catch-all (
_) do obsługi wariantów, a później, przy dodawaniu nowych wariantów, doprowadziło to do tego, że logika cicho ignorowała nowe przypadki, co stało się przyczyną trudnych do znalezienia defektów.