Generic Data Type
- 구체화된 타입이나 다른 속성들에 대해 추상화된 대리인
- 코드를 작성하고 컴파일할 때 generic이 실제로 어떻게 완성되는지 알 필요 없이 generic의 동작 혹은 다른 generic과 어떻게 연관되는지와 같은 속성을 표현 가능
- 구체화된 타입 대신 몇몇 제네릭 타입의 파라미터를 갖는 함수 작성 가능
Option<T>
, Vec<T>
, HashMap<K, V>
, Result<T, E>
등이 해당
함수 정의 내에서 사용
fn largest<T>(list: &[T]) -> T {
let mut largest = list[0];
for &item in list.iter() {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let numbers = vec![34, 50, 25, 100, 65];
let result = largest(&numbers);
println!("The largest number is {}", result);
let chars = vec!['y', 'm', 'a', 'q'];
let result = largest(&chars);
println!("The largest char is {}", result);
}
- 위는
largest
함수를 i32
와 char
에 대해 두 번 정의하지 않고 generic data type을 이용해 통합된 형태로 정의한 코드
- 위 코드 실행 시 컴파일 에러가 발생하는데 이는 다음 장에서 언급할 trait에 관한 문제이므로 다음 장에서 알아 볼 것임
구조체 정의 내에서 사용
struct Point<T> {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
}
Point
정의 내에서 단 하나의 generic type을 사용했기 때문에 x
와 y
가 동일한 타입을 가짐
x
와 y
가 서로 다른 타입을 갖도록 하려면 아래처럼 두 개의 generic type 필요
struct Point<T, U> {
x: T,
y: U,
}
fn main() {
let both_integer = Point { x: 5, y: 10 };
let both_float = Point { x: 1.0, y: 4.0 };
let integer_and_float = Point { x: 5, y: 4.0 };
}
열거형 정의 내에서 사용
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
메소드 정의 내에서 사용
struct Point<T, U> {
x: T,
y: U,
}
impl<T, U> Point<T, U> {
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point {
x: self.x,
y: other.y,
}
}
}
fn main() {
let p1 = Point { x: 5, y: 10.4 };
let p2 = Point { x: "Hello", y: 'c'};
let p3 = p1.mixup(p2);
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}
Generic을 이용한 코드의 성능
- generic 사용 시 구체적 타입을 명시했을 때와 비교해 전혀 느려지지 않음
- 컴파일 타임에 generic을 사용하는 코드에 대해 단형성화(monomorphization)을 수행
- 단형성화: generic 코드를 실제 구체적 타입에 대한 코드로 바꾸는 과정