다중 경계
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가 Display와 Summary를 모두 implements해야 한다"는 뜻입니다. 함수 내부에서는 두 trait의 capabilities를 모두 사용할 수 있습니다. {}를 사용한 출력(Display에서 제공)과 summarize() 호출(Summary에서 제공)이 그 예입니다.
필요한 만큼 많은 트레이트를 연결할 수 있습니다:
fn process<T: Display + Summary + Clone>(item: T) {
// 출력하고, 요약하고, 그리고 복제할 수 있음
}
이 패턴은 function이 여러 동작에 의존할 때 필수적입니다. any 타입을 받아 작동하기를 기대하는 대신, 필요한 capabilities를 정확히 명시하고 컴파일러가 컴파일 시점에 이를 적용하도록 합니다.
챌린지
쉬움여러 capabilities를 갖도록 요구하는 product inspection system을 만들어 봅시다! custom trait와 standard trait를 모두 implements하는 타입만 받아들이는 generic function을 만들면서, + syntax가 여러 bounds를 결합하는 방식을 보여 줍니다.
코드를 두 파일에 나누어 구성합니다.
product.rs:inspectmethod를 포함하는 publicInspectabletrait를 Define합니다. 이 method는&self를 받고 inspection details가 담긴String을 반환합니다. 그런 다음 publicname(String) 및serial(u32)fields를 가진 publicGadgetstruct를 만듭니다. Gadget은Inspectable(Inspecting: {name}을 반환)과std::fmt::Display({name} (SN: {serial})형식으로 지정)를 모두 implements해야 합니다. 마지막으로Display와Inspectable을 모두 implements하는 any typeT를 받는 public generic functionfull_report를 만듭니다. 이 function은 두 lines를 print해야 합니다. 첫 번째는{}formatter를 사용한 item이고, 두 번째는inspect()를 calling한 result입니다.main.rs: product module을 가져오고 제공된 inputs를 사용하여Gadgetinstance를 만듭니다. 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가 Smartwatch와 98765인 경우:
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 호출
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Rust 컴파일러