트레이트는 러스트에서 공통된 동작(메서드)을 정의하는 기능으로, 다른 언어의 인터페이스(interface)나 추상 클래스와 비슷합니다.
예를 들어, Summary라는 트레이트를 만들고 특정 타입(Tweet, NewsArticle 등)에 대해 이 트레이트를 구현하면, 해당 타입에서 Summary가 제공하는 메서드를 사용할 수 있습니다.
트레이트를 정의하는 기본적인 문법은 다음과 같습니다:
pub trait Summary {
fn summarize(&self) -> String;
}
trait Summary로 트레이트를 정의합니다. 이제 Summary 트레이트를 특정 타입에 구현하려면 impl을 사용합니다:
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 Summary for Tweet 형태로 Tweet 타입에 대해 Summary 트레이트를 구현했습니다. summarize 메서드의 실제 동작을 정의해야 합니다. 트레이트를 구현한 타입에서는 일반적인 메서드 호출처럼 사용할 수 있습니다.
fn main() {
let tweet = Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
};
println!("1 new tweet: {}", tweet.summarize());
}
출력 결과:
1 new tweet: horse_ebooks: of course, as you probably already know, people
tweet.summarize()를 호출하면 Summary 트레이트에서 정의한 summarize 메서드가 실행됩니다. 러스트에서는 임의의 타입에 대해 임의의 트레이트를 구현할 수 없습니다.
✅ 가능: 자신이 만든 타입에 외부 트레이트 구현
use std::fmt;
struct MyType;
impl fmt::Display for MyType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MyType 입니다!")
}
}
MyType은 내가 만든 타입 → 표준 라이브러리의 Display 트레이트를 구현 가능 ✅ 가능: 자신이 만든 트레이트를 외부 타입에 구현
trait MyTrait {
fn my_method(&self) -> String;
}
impl MyTrait for Vec<i32> {
fn my_method(&self) -> String {
format!("이 벡터에는 {}개의 요소가 있습니다.", self.len())
}
}
Vec<i32>는 외부 타입이지만, MyTrait은 내가 만든 트레이트 → 구현 가능 ❌ 불가능: 외부 타입에 외부 트레이트 구현
// std::fmt::Display (외부 트레이트) 를 Vec<i32> (외부 타입) 에 구현하려고 하면 오류 발생
impl fmt::Display for Vec<i32> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
Vec<i32>도 외부 타입, Display도 외부 트레이트 → 러스트에서 허용하지 않음 trait 트레이트명으로 정의하고, impl 트레이트 for 타입으로 구현한다. use를 통해 스코프로 가져와야 한다.