트레잇(Traits)
러스트의 트레잇은 굳이 다른 언어로 말하자면 인터페이스라 할 수 있음.
트레잇의 규칙 및 성질
- 트레잇은 하나의 타입으로 취급됨. 같은 트레잇을 구현한 타입은 트레잇으로 같은 타입으로 동작할 수 있음. (제너릭)
- 트레잇은 추상 메서드, 디폴트 메서드를 가질 수 있음.
- 트레잇을 구현하는 타입은 반드시 트레잇의 모든 추상 메서드를 구현해야 함. (디폴트 메서드는 반드시 구현할 필요 없음)
- 한 타입이 트레잇의 디폴트 메서드를 구현하면 오버라이딩 되어 구현된 메서드가 실행됨.
- 한 타입은 여러 트레잇을 구현할 수 있음.
- 한 타입이 여러 트레잇을 구현할 때, 메서드 시그니처가 겹치면 컴파일 에러 발생.
- 외부 타입으로 로컬 트레잇을 구현할 수 있음.
- 로컬 타입이 외부 트레잇을 구현할 수 있음.
- 외부 타입으로 외부 트레잇을 구현할 수 없음. (orphan rule)
트레잇 정의 및 구현
트레잇 정의.
pub trait Summarizable {
fn summary(&self) -> String;
fn summary_nicer(&self) { // 디폴트 메서드(구현할 필요 없음)
// do something..
}
}
그리고 아래와 같이 구현. summary_nicer 메서드는 디폴트라 구현하지 않아도 됨.
pub struct NewsArticle {
}
impl Summarizable for NewsArticle {
fn summary(&self) -> {
// do something..
}
}
트레잇 제한
아래는 트레잇을 타입으로 하여 메서드 파라미터 제한.
pub fn notify<T: Summarizable>(item: T) {
println!("Breaking news! {}", item.summary());
}
아래처럼 and 조건을 걸듯, 여러 트레잇을 구현한 타입으로 제한할 수도 있음.
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
위처럼 파라미터가 많고 제한 트레잇이 많은 경우 보기가 불편함. 아래와 같이 where 키워드를 사용하여 트레잇을 예쁘게 명시할 수 있음.
fn some_function<T, U>(t: T, u: U) -> i32
where T: Display + Clone,
U: Clone + Debug
{
아래와 같이 impl 에 트레잇의 제너릭 타입과 타입의 제너릭 타입을 지정하여 제한된 메서드 구현을 할 수 있음.
trait movable<T> {
fn goto(&self);
}
struct Location<T> {
X: i32,
y: i32,
loc_type: T,
}
impl movable<i32> for Location<i32> {
fn goto(&self) {
// do something..
}
}
위의 경우, 같은 Location 인스턴스라도 Location<i32> 타입만 movable 을, 그것도 movable<i32> 를 구현하여 movable<i32> 타입으로 동작할 수 있음. Location<String> 타입 인스턴스는 goto 메서드를 호출할 수 없음.
impl 에 다중 트레잇 타입을 한정하는 경우 아래와 같이 하면 됨.
struct Location<T> {
X: i32,
y: i32,
loc_type: T,
}
impl<T: Display + PartialOrd> Location<T> {
fn do_something(&self) {
// do something..
}
}
Display + PartialOrd 트레잇을 모두 구현한 타입의 Location 만이 do_something 메서드를 구현.
'Rust' 카테고리의 다른 글
클로저(심화) (0) | 2018.03.07 |
---|---|
라이프타임 (0) | 2018.02.28 |
제너릭 타입 (0) | 2018.02.27 |
에러 핸들링(Result) (0) | 2018.02.26 |
에러 핸들링(panic) (0) | 2018.02.26 |