Menu
Coddy logo textTech

다중 경계

Coddy Rust 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 41번째.

때로는 단일 trait 제약만으로는 충분하지 않습니다. 출력할 수도 있고 요약을 제공할 수도 있는 제네릭 타입이 필요할 수 있습니다. Rust에서는 + 구문을 사용하여 여러 trait을 요구할 수 있습니다.

타입이 두 가지 trait를 구현해야 한다고 지정하는 방법은 다음과 같습니다.

use std::fmt::Display;

trait Summary {
    fn summarize(&self) -> String;
}

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

T: Display + Summary라는 bound는 "T가 DisplaySummary를 모두 implements해야 한다"는 뜻입니다. 함수 내부에서는 두 trait의 capabilities를 모두 사용할 수 있습니다. {}를 사용한 출력(Display에서 제공)과 summarize() 호출(Summary에서 제공)이 그 예입니다.

필요한 만큼 많은 트레이트를 연결할 수 있습니다:

fn process<T: Display + Summary + Clone>(item: T) {
    // 출력하고, 요약하고, 그리고 복제할 수 있음
}

이 패턴은 function이 여러 동작에 의존할 때 필수적입니다. any 타입을 받아 작동하기를 기대하는 대신, 필요한 capabilities를 정확히 명시하고 컴파일러가 컴파일 시점에 이를 적용하도록 합니다.

challenge icon

챌린지

쉬움

여러 capabilities를 갖도록 요구하는 product inspection system을 만들어 봅시다! custom trait와 standard trait를 모두 implements하는 타입만 받아들이는 generic function을 만들면서, + syntax가 여러 bounds를 결합하는 방식을 보여 줍니다.

코드를 두 파일에 나누어 구성합니다.

  • product.rs: inspect method를 포함하는 public Inspectable trait를 Define합니다. 이 method는 &self를 받고 inspection details가 담긴 String을 반환합니다. 그런 다음 public name (String) 및 serial (u32) fields를 가진 public Gadget struct를 만듭니다. Gadget은 Inspectable (Inspecting: {name}을 반환)과 std::fmt::Display ({name} (SN: {serial}) 형식으로 지정)를 모두 implements해야 합니다. 마지막으로 DisplayInspectable을 모두 implements하는 any type T를 받는 public generic function full_report를 만듭니다. 이 function은 두 lines를 print해야 합니다. 첫 번째는 {} formatter를 사용한 item이고, 두 번째는 inspect()를 calling한 result입니다.
  • main.rs: product module을 가져오고 제공된 inputs를 사용하여 Gadget instance를 만듭니다. gadget을 인수로 full_report를 Call하여 두 trait requirements를 모두 충족한다는 것을 보여 줍니다.

multiple bounds의 power는 full_report function이 두 traits의 capabilities를 모두 사용할 수 있다는 것입니다. 즉 item을 보기 좋게 Display하면서 AND inspection details도 가져올 수 있으며, 이 모든 것이 compile time에 보장됩니다.

출력에는 display format과 inspection result가 모두 표시되어야 합니다.

{name} (SN: {serial})
Inspecting: {name}

예를 들어 inputs가 Smartwatch98765인 경우:

Smartwatch (SN: 98765)
Inspecting: Smartwatch

두 개의 inputs를 받습니다. gadget name과 serial number이며, serial number는 u32로 parse합니다.

직접 해보기

mod product;

use product::{Gadget, full_report};

fn main() {
    // 입력 읽기
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    let mut serial_input = String::new();
    std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
    let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
    
    // TODO: name과 serial로 Gadget 인스턴스 생성
    
    // TODO: gadget으로 full_report 호출
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Rust 컴파일러