C의 enum
C에서의 enum은 상수 값에 의미를 부여하는 데 주로 사용됩니다.
#include <stdio.h>
enum Color {
Red = 1,
Green = 2,
Blue = 4
};
int main() {
enum Color myColor = Blue;
printf("My color is: %d\n", myColor); // 출력: My color is: 4
return 0;
}
반드시 각 필드에 정수 값이 할당된다는 특징이 있습니다.
enum Color {
Red, // 0
Green, // 1
Blue // 2
};
만약 값을 할당하지 않아도 자동으로 순서대로 0부터 값이 할당됩니다.
Rust의 enum
일종의 user-defined datatype을 모아둔 set입니다.
enum WebEvent {
// An `enum` variant may either be `unit-like`,
PageLoad,
PageUnload,
// like tuple structs,
KeyPress(char),
Paste(String),
// or c-like structures.
Click { x: i64, y: i64 },
Number(i32), // 단일 정수 값
}
보시다시피 유연하게 다양한 타입의 값을 가질 수 있습니다.
이를 match 문법과 연계하여 다양한 데이터 타입으로 하여금
각각의 타입에 맞게 작동하도록 구현할 수 있습니다.
fn inspect(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("page loaded"),
WebEvent::PageUnload => println!("page unloaded"),
// Destructure `c` from inside the `enum` variant.
WebEvent::KeyPress(c) => println!("pressed '{}'.", c),
WebEvent::Paste(s) => println!("pasted \"{}\".", s),
// Destructure `Click` into `x` and `y`.
WebEvent::Click { x, y } => {
println!("clicked at x={}, y={}.", x, y);
},
}
}
fn main() {
let pressed = WebEvent::KeyPress('x');
// `to_owned()` creates an owned `String` from a string slice.
let pasted = WebEvent::Paste("my text".to_owned());
let click = WebEvent::Click { x: 20, y: 80 };
let load = WebEvent::PageLoad;
let unload = WebEvent::PageUnload;
inspect(pressed);
inspect(pasted);
inspect(click);
inspect(load);
inspect(unload);
}
type aliases
이러한 enum의 타입뿐만 아니라 어떤 타입형에
의미를 부여하기 위해 각 타입의 이름을 바꾸기 위해
C++ 에선 typedef를 사용했던 것처럼 Rust도 그러한
별칭 사용을 허용합니다.
typedef int Kilometers;
int main() {
Kilometers distance = 100;
std::cout << "Distance: " << distance << " km" << std::endl;
return 0;
}
위는 C++의 예시입니다.
아래는 Rust의 예시입니다.
type Kilometers = i32;
fn main() {
let distance: Kilometers = 100;
println!("Distance: {} km", distance);
}
이러한 특징을 이용해 변수형에 의미를 부여할 뿐만 아니라
좀 enum이 이름이 길거나 하면 여러가지 의도로 사용될 수 있고요.
enum VeryVerboseEnumOfThingsToDoWithNumbers {
Add,
Subtract,
}
// Creates a type alias
type Operations = VeryVerboseEnumOfThingsToDoWithNumbers;
fn main() {
// We can refer to each variant via its alias, not its long and inconvenient
// name.
let x = Operations::Add;
}
그 예시로 Self alias입니다.
enum VeryVerboseEnumOfThingsToDoWithNumbers {
Add,
Subtract,
}
impl VeryVerboseEnumOfThingsToDoWithNumbers {
fn run(&self, x: i32, y: i32) -> i32 {
match self {
Self::Add => x + y,
Self::Subtract => x - y,
}
}
}
fn main() {
let add = VeryVerboseEnumOfThingsToDoWithNumbers::Add;
let subtract = VeryVerboseEnumOfThingsToDoWithNumbers::Subtract;
println!("Add: {}", add.run(5, 3)); // 출력: Add: 8
println!("Subtract: {}", subtract.run(5, 3)); // 출력: Subtract: 2
}
"VeryVerboseEnumOfThingsToDoWithNumbers" 라는 enum에
메소드를 추가하기 위해 impl을 통해 Add 타입과, Subtract 타입에 맞는
행동을 구현합니다. 이때 기존의 enum이 아니라
Self:: 라는 구문을 통해 VeryVerboseEnumOfThingsToDoWithNumbers라는
기존의 enum 값을 대체할 수 있습니다.
use
C++로 치면 using namespace std; 를 통해,
std::cout을 cout으로 줄여 쓸 수 있는 것처럼,
enum이나 다른 모듈에 정의된 기능들을 쓸 수 있는 겁니다.
예를 들어,
enum Stage {
Beginner,
Advanced,
}
enum Role {
Student,
Teacher,
}
fn main() {
// Explicitly `use` each name so they are available without
// manual scoping.
use crate::Stage::{Beginner, Advanced};
// Automatically `use` each name inside `Role`.
use crate::Role::*;
// Equivalent to `Stage::Beginner`.
let stage = Beginner;
// Equivalent to `Role::Student`.
let role = Student;
}
기존에 enum으로 정의된 Stage, Role 내부 변형들을
사용하기 위해 Stage::Beginner를 통해 stage라는 식별자에
enum 타입형을 할당해야 하지만 use를 통해
모듈 이름을 생략합니다.
C style enum
C에서는 각 enum이 어떤 값을 가지게 정의합니다.
위에서 보여드린 예시처럼 어떤 리터럴 값을 정의하거나,
정의하지 않는다면 0부터 차례대로 할당됩니다.
하지만 Rust엔 unit 타입형이 존재하기에
C에서 처럼 쉽게 출력할 수 없습니다.
enum Number {
Zero,
One,
Two,
}
fn main() {
// `enums` can be cast as integers.
println!("zero is {}", Number::Zero);
println!("one is {}", Number::One as i32);
}
예를 들어 이렇게 타입형과 값이 명시되지 않은
Number enum 타입 내 각 변형들은
C와 달리 default로 0, 1, 2.. 값을 가지지 않습니다.
그래서,
println!("zero is {}", Number::Zero);
이러한 구절의 경우 다음과 같은 에러를 발생시킵니다.
그런데, enum의 유닛 타입형의 경우 타입 캐스팅은 가능합니다.
enum Number {
Zero,
One,
Two,
}
fn main() {
// `enums` can be cast as integers.
println!("zero is {}", Number::Zero as i32);
println!("one is {}", Number::One as i32);
println!("two is {}", Number::Two as i32);
}
이렇게 각 타입을 i32로 타입 캐스팅을 하면
값이 출력됩니다.
'프로그래밍 언어 > [Rust]' 카테고리의 다른 글
[Rust] Types (1) | 2025.01.03 |
---|---|
[Rust] Variable의 특성 (0) | 2024.12.30 |
[Rust] 구조체 (0) | 2024.12.30 |
[Rust] Ownership과 Reference (0) | 2024.12.30 |
[Rust] 기본 골자 (2) | 2024.12.26 |