제네릭
- 함수 시그니처나 구조체의 아이템에 다양한 데이터 타입을 쓰도록 할수 있다.
fn largest<T>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
- T를 이용해 제네릭 함수를 선언한 예시
- 허나 이 경우 T가 비교문이 구현된것인지 확인할수 없어 에러가 나온다.
제네릭 구조체
struct Point<T> {
x: T,
y: T,
}
struct Point<T, U> {
x: T,
y: U,
}
제네릭 열거형
enum Option<T> {
Some(T),
None,
}
제네릭 메서드
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
- 특정 타입에만 정의할수도 있다.
- impl 뒤에 <T> 를 붙혀 Point 뒤가 제네릭임을 알린다.
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
- Point 뒤가 제네릭임을 알릴 필요가 없어 impl 뒤에 아무것도 없다.
- 제네릭 코드를 사용하는 코드를 컴파일시 구체적인 타입으로 변환하기 때문에 성능적 차이가 없다.
트레이트
- 특정한 타입이 가지며 다른 타입과 공유하는 기능
- interface
정의하기
pub trait Summary {
fn summarize(&self) -> String;
}
트레이트 구현하기
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
- impl 트레이트 이름 for 구조체 이름 {
// 구현
}
트레이트에 기본 구현 추가
pub trait Summary {
fn summarize(&self) -> String {
String::from("(Read more...)")
}
}
impl Summary for NewsArticle {}
// 와 같이 사용 가능하다.
매개변수로 트레이트
pub fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
- impl 키워드와 구현한 트레이트의 이름이 주어진다.
- Summary trait 가 구현된 것만 사용하게 한다.
pub fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
- 와 같이 사용할수도 있다.
- 둘이 같은 타입으로 강제된다.
pub fn notify(item: &(impl Summary + Display)) {
pub fn notify<T: Summary + Display>(item: &T) {
fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {
fn some_function<T, U>(t: &T, u: &U) -> i32
where
T: Display + Clone,
U: Clone + Debug,
{
Trait를 구현하는 타입을 반환
fn returns_summarizable() -> impl Summary {
Tweet {
username: String::from("horse_ebooks"),
content: String::from(
"of course, as you probably already know, people",
),
reply: false,
retweet: false,
}
}
조건부 메서드
impl<T: Display + PartialOrd> Pair<T> {
fn cmp_display(&self) {
if self.x >= self.y {
println!("The largest member is x = {}", self.x);
} else {
println!("The largest member is y = {}", self.y);
}
}
}
- T가 Display와 PartialOrd를 모두 구현했을때만 메서드가 구현된다.
impl<T: Display> ToString for T {
// --생략--
}
- Display 가 구현된 모든 타입에서 ToString 을 구현한다.