18.1 열거
백만 분의 1 문제, 수많은 옵션 중에서 하나를 선택하는 문제처럼 Rust는 이를 표현하기 위해 새로운 데이터 유형을 제공합니다.
이 새로운 데이터 유형은 열거형 (영어 enum) 입니다 .
즉, 열거형은 변경 가능한 여러 목록 중 하나를 선택하는 데 사용됩니다.
18.2 열거형 정의
Rust 언어는 열거형을 정의하기 위한 enum 키워드를 제공합니다.
열거형을 정의하는 구문 형식은 다음과 같습니다.
- enum enum_name {
- variant1,
- variant2,
- variant3
- }
예를 들어 위의 바나나 및 파인애플 옵션에 대해 과일 열거형을 정의할 수 있습니다.
- enum Fruits {
- 바나나,
- 파인애플,
- 포도,
- 사과
- }
18.3 열거형 사용하기
열거형이 정의된 후에는 열거형을 사용하는 방법이 매우 간단합니다. 즉, 열거형 이름::열거형 값입니다. 구문 형식은 다음과 같습니다
- enum_name::variant
예를 들어, 위 열거형에서 바나나를 선택하면 할당 구문은 다음과 같습니다.
- let selected = Fruits::바나나;
유형을 명시적으로 지정해야 하는 경우 다음을 수행할 수 있습니다.
- let selected: Fruits = Fruits::바나나;
18.3.1 예
다음 예제에서는 열거형의 기본적인 사용 방법과 사례를 보여줍니다.
먼저 바나나, 배, 만다린, 가지라는 4개의 열거형 값을 갖는 Fruits 열거형을 정의했습니다.
println!()은 열거형을 인쇄하는 데 사용됩니다.
참고: 나중에 열거형 앞에 #[derive(Debug)]를 소개하겠습니다.
- #[derive(Debug)]
- enum Fruits {
- 바나나,
- 파인애플,
- 포도,
- 사과
- }
-
- fn main() {
- let selected = Fruits::바나나;
- println!("{:?}",selected);
- }
위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.
- 바나나
18.4 #[derive(Debug)] 주석
Enum Fruits 앞에 #[derive(Debug)]가 있는 것을 보셨을 것입니다.
이 #[derive(Debug)] 문의 기능은 무엇입니까?
먼저 설명하지 않겠습니다. #[derive(Debug)] 를 제거하고 살펴보겠습니다.
- enum Fruits {
- 바나나,
- 파인애플,
- 포도,
- 사과
- }
-
- fn main() {
- let selected = Fruits::바나나;
- println!("{:?}",selected);
- }
위의 Rust 코드를 컴파일하거나 오류를 보고하면 다음과 같습니다.
- error[E0277]: `Fruits` doesn't implement `std::fmt::Debug`
- --> src/main.rs:11:20
- |
- 11 | println!("{:?}",selected);
- | ^^^^^^^^ `Fruits` cannot be formatted using `{:?}`
- |
- = help: the trait `std::fmt::Debug` is not implemented for `Fruits`
- = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
- = note: required by `std::fmt::Debug::fmt`
이 오류의 의미는 우리의 Enum Fruits 열거가 std::fmt::Debug 특성을 구현하지 않는다는 것입니다.
나중에 특성을 소개하겠습니다. 여기서는 특성을 인터페이스로 처리하면 됩니다.
컴파일을 통과하려면 std::fmt::Debug 특성을 이미 구현한 것에서 열거형을 파생시키거나 파생시켜야 합니다. 이에 대한 가장 일반적인 것은 디버그입니다.
따라서 #[derive(Debug)] 주석의 기능은 Debug에서 파생된 Fruit을 만드는 것입니다.
하지만 실제로는 #[derive(Debug)] 주석을 추가하더라도 여전히 경고가 표시됩니다.
- #[derive(Debug)]
- enum Fruits {
- 바나나,
- 파인애플,
- 포도,
- 사과
- }
-
- fn main() {
- let selected = Fruits::바나나;
- println!("{:?}",selected);
- }
컴파일 결과는 다음과 같습니다
- warning: variants `파인애플`, `포도`, and `사과` are never constructed
--> src/main.rs:4:3
|
2 | enum Fruits {
| ------ variants in this enum
3 | 바나나,
4 | 파인애플,
| ^^^^^^^^
5 | 포도,
| ^^^^
6 | 사과
| ^^^^
|
= note: `Fruits` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` on by default
이는 아마도 우리가 사용하지 않은 열거형이 아직 구성되지 않았음을 의미할 것입니다.
- variant is never constructed: 정확히 무엇을 의미합니까?
18.5 구조체형 struct와 열거형 enum
지금까지 우리는 맞춤화할 수 있는 두 가지를 배웠습니다.
- 하나는 구조 유형 struct 입니다.
- 다른 하나는 열거형 enum입니다.
그들 사이의 관계와 연결은 무엇입니까?
약간의 관계가 있다면 열거형 enum을 구조체의 멤버변수의 데이터형으로 사용할 수 있다는 점이다.
18.5.1 예
다음 코드에서는 성별을 나타내는 열거형 GenderCategory를 정의합니다. 열거형 값은 남성과 여성을 각각 나타냅니다.
제3의 성별이 있나요? 여기서는 무시하세요.
동시에 우리는 사람을 설명하기 위해 Person 구조를 정의했습니다. 이 Person 구조는 GenderCategory 열거형을 멤버 변수 성별의 데이터 유형으로 사용합니다.
따라서 Person 구조의 일반 멤버 변수는 남성과 여성이라는 두 가지 값만 가질 수 있습니다.
- // 오류를 저장하려면 #[derive(Debug)]를 추가하세요.
- #[derive(Debug)]
- enum GenderCategory {
- Male,Female
- }
-
- // 오류를 저장하려면 #[derive(Debug)]를 추가하세요.
- #[derive(Debug)]
- struct Person {
- name:String,
- gender:GenderCategory
- }
-
- fn main() {
- let p1 = Person {
- name:String::from("러스트 튜토리얼"),
- gender:GenderCategory::Female
- };
- let p2 = Person {
- name:String::from("Admin"),
- gender:GenderCategory::Male
- };
- println!("{:?}",p1);
- println!("{:?}",p2);
- }
위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.
- Person { name: "러스트 튜토리얼", gender: Female }
- Person { name: "Admin", gender: Male }
18.6 옵션 열거
Rust 언어 코어와 표준 라이브러리에는 많은 내장 열거형이 있으며, 그중 우리가 자주 다루는 열거형이 하나 있는데 바로 Option 열거형입니다.
Option 열거형은 선택적 옵션을 나타냅니다. None과 Some(T)의 두 가지 열거 값을 갖습니다.
- 없음은 선택 사항이 없음을 의미합니다.
- Some(T)은 없어도 되는 것을 의미하므로 값이 있어야 한다는 것, 즉 데이터형이 있어야 한다는 것입니다.
18.6.1 Option 열거형의 정의코드는 다음과 같다
- enum Option<T> {
- Some(T), // 값을 반환하는 데 사용
- None // Rust는 null을 지원하지 않지만 null을 반환하는 데 사용됩니다.
- the null keyword
- }
Rust 언어는 null 키워드를 지원하지 않으며 대신 None을 사용하여 없음을 의미합니다.
Option 열거형은 반환과 값을 나타낼 수 있거나 반환을 나타내지만 값이 없는 데 사용될 수 있기 때문에 함수에서 반환 값으로 자주 사용됩니다.
함수에 반환 값이 있으면 Some(data)을 반환할 수 있습니다. 함수에 반환 값이 없으면 None을 반환할 수 있습니다.
그래도 이해가 안 되시면 예시를 보시면 됩니다.
18.6.2 예
다음 예에서는 Option 열거형을 반환 값 유형으로 사용하여 is_even() 함수를 정의합니다.
is_even() 함수에 전달된 매개변수가 짝수이면 전달된 매개변수가 반환되고, 홀수이면 None이 반환됩니다.
- fn main() {
- let result = is_even(3);
- println!("{:?}",result);
- println!("{:?}",is_even(30));
- }
- fn is_even(no:i32)->Option<bool> {
- if no %2 == 0 {
- Some(true)
- } else {
- None
- }
- }
위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.
- None
- Some(true)
18.7 match 문과 열거형
열거의 또 다른 중요한 작업은 열거 값을 판단하는 것입니다. 열거형 값을 결정하는 데 == 비교 연산자는 효과가 없습니다.
정확하게 말하면 오류가 보고됩니다.
- #[derive(Debug)]
- enum Fruits {
- 바나나,
- 파인애플,
- 포도,
- 사과
- }
-
- fn main() {
- let selected = Fruits::바나나;
- if selected == Fruits::바나나 {
- println!("바나나를 선택했어요");
- } else {
- println!("다른 걸 선택했어요");
- }
- println!("{:?}",selected);
- }
컴파일 오류
- --> src/main.rs:11:17
- |
- 11 | if selected == Fruits::Banana {
- | -------- ^^ -------------- Fruits
- | |
- | Fruits
- |
- = note: an implementation of `std::cmp::PartialEq` might be missing for `Fruits`
열거형 변수의 값을 결정하기 위해 사용할 수 있는 유일한 연산자는 match 문입니다.
match 문에 대해서는 이미 배웠으므로 여기서는 소개하지 않겠습니다. 바로 예제로 가서 match 문을 사용하여 열거형 값을 결정하는 방법을 살펴보겠습니다.
18.7.1 예
다음 코드에서는 CarType 열거형과 CarType 열거형 변수를 받아들이고 match 문을 사용하여 열거형 변수의 값을 결정하는 함수 print_size()를 정의합니다.
- enum CarType {
- Hatch,
- Sedan,
- SUV
- }
- fn print_size(car:CarType) {
- match car {
- CarType::Hatch => {
- println!("Small sized car");
- },
- CarType::Sedan => {
- println!("medium sized car");
- },
- CarType::SUV =>{
- println!("Large sized Sports Utility car");
- }
- }
- }
- fn main(){
- print_size(CarType::SUV);
- print_size(CarType::Hatch);
- print_size(CarType::Sedan);
- }
위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.
- Large sized Sports Utility car
- Small sized car
- medium sized car
18.8 match 문과 Option 유형
match 문은 열거형 변수의 값을 비교하고 판단하는 데 사용할 수 있으므로 위에서 언급한 Option 열거형에도 match 문을 사용합니다.
실제로 match 문과 Option 유형의 조합은 Option 열거형의 강력한 기능을 반영할 수 있습니다.
- fn main() {
- match is_even(5) {
- Some(data) => {
- if data==true {
- println!("Even no");
- }
- },
- None => {
- println!("not even");
- }
- }
- }
- fn is_even(no:i32)->Option<bool> {
- if no%2 == 0 {
- Some(true)
- } else {
- None
- }
- }
위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.
- not even
18.9 데이터 유형이 있는 일치 문 및 열거형
Rust의 Enum 값은 고유한 데이터 유형을 가질 수 있습니다. 데이터 유형이 포함된 열거형 값 구문은 일치 문과 열거형을 전례 없는 수준으로 완전히 밀어냅니다.
더욱 강력한 점은 각 열거형 값이 서로 다른 데이터 유형을 가질 수 있다는 것입니다.
데이터 유형이 있는 열거형 값의 구문 형식은 다음과 같이 매우 간단합니다.
- enum enum_name {
- variant1(data_type1),
- variant2(data_type2),
- variant3(data_type1)
- }
예를 들어 다음 열거형은
- enum GenderCategory {
- Name(String),
- Usr_ID(i32)
- }
열거형 GenderCategory에는 String과 i32라는 서로 다른 데이터 유형을 갖는 두 개의 열거형 값인 Name과 User_ID가 있습니다.
18.9.1 예
다음 예에서는 데이터 유형으로 GenderCategory 열거형을 정의합니다. 그런 다음 데이터 유형으로 열거 값을 초기화하고 일치 문의 판단을 보여줍니다.
- // 오류보고
- #[derive(Debug)]
- enum GenderCategory {
- Name(String),Usr_ID(i32)
- }
- fn main() {
- let p1 = GenderCategory::Name(String::from("Mohtashim"));
- let p2 = GenderCategory::Usr_ID(100);
- println!("{:?}",p1);
- println!("{:?}",p2);
-
- match p1 {
- GenderCategory::Name(val)=> {
- println!("{}",val);
- }
- GenderCategory::Usr_ID(val)=> {
- println!("{}",val);
- }
- }
- }
위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.
- Name("Mohtashim")
- Usr_ID(100)
- Mohtashim
현재 콘텐츠 저작권은 chapin666 또는 그 계열사에 있습니다.