Menu
Coddy logo textTech

where 절

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

trait 바운드를 더 추가하면 함수 시그니처를 읽기 어려워질 수 있습니다. 여러 제네릭 매개변수를 사용하는 함수에서 각 매개변수가 여러 트레이트를 요구하는 경우를 생각해 보세요.

fn complex_operation<T: Display + Clone, U: Debug + Summary>(first: T, second: U) {
    // ...
}

이 방식도 작동하지만, 시그니처가 점점 복잡해지고 있습니다. where 절은 매개변수 목록 뒤로 트레이트 경계를 옮겨 더 깔끔한 대안을 제공합니다:

fn complex_operation<T, U>(first: T, second: U)
where
    T: Display + Clone,
    U: Debug + Summary,
{
    // ...
}

두 버전은 기능적으로 동일합니다. where 절은 순전히 가독성을 위한 것입니다. 각 타입의 요구 사항이 각자의 줄에 표시되므로, 각 generic 매개변수에 필요한 사항을 쉽게 훑어볼 수 있습니다.

where clause는 bounds가 복잡하거나 generic 매개변수가 많을 때 특히 유용합니다. 한눈에 function 이름과 매개변수를 확인할 수 있으며, 제약 조건은 아래에 별도로 나열됩니다. bounds가 단순한 T: Trait를 넘어설 때 대부분의 Rust 코드베이스에서 선호되는 스타일입니다.

challenge icon

챌린지

쉬움

복잡한 trait bound를 읽기 쉽게 유지하기 위해 where clause를 사용하는 데이터 처리 시스템을 만들어 봅시다! 여러 type parameter를 사용하는 generic function을 만들고, 각 parameter에 서로 다른 trait를 요구한 다음 where 구문을 사용해 bound를 깔끔하게 정리합니다.

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

  • processor.rs: 두 개의 public trait와 두 trait를 모두 사용하는 generic function을 Define합니다:
    • Summarize: &self를 받고 String을 반환하는 summary method를 가진 trait
    • Validate: &self를 받고 bool을 반환하는 validate method를 가진 trait
    그런 다음 서로 다른 generic type의 parameter 두 개를 받는 process_items라는 public generic function을 만듭니다. where clause를 사용해 첫 번째 type이 CloneSummarize를 모두 implement해야 하고, 두 번째 type이 Validate를 implement해야 한다고 지정합니다. function은 첫 번째 item의 요약을 출력한 다음, 두 번째 item이 유효한지 출력해야 합니다.
  • main.rs: 필요한 trait를 implement하는 public struct 두 개를 만듭니다:
    • Article: public title field (String)를 가집니다. Article: {title}을 반환하도록 Summarize를 implement하고, Clone을 derive합니다.
    • Form: public filled field (bool)를 가집니다. filled의 값을 반환하도록 Validate를 implement합니다.
    제공된 input을 사용해 Article과 Form을 만든 다음, 두 값을 사용해 process_items를 호출합니다.

where clause를 사용하면 모든 bound를 angle bracket 안에 몰아넣는 것보다 function signature가 훨씬 깔끔해집니다. 각 type의 요구 사항이 각자의 줄에 표시되므로, 각 generic parameter에 무엇이 필요한지 쉽게 확인할 수 있습니다.

출력에는 요약 다음에 validation 결과가 표시되어야 합니다:

Article: {title}
Valid: {true/false}

예를 들어 input이 Rust Tipstrue인 경우:

Article: Rust Tips
Valid: true

input이 Breaking Newsfalse인 경우:

Article: Breaking News
Valid: false

두 개의 input을 받습니다. 하나는 article title이고, 다른 하나는 form이 filled되었는지 여부입니다(bool로 parse).

직접 해보기

mod processor;

use processor::{Summarize, Validate, process_items};
use std::io;

// TODO: 공개 title 필드(String)를 가진 공개 구조체 Article을 정의하세요
// Article에 Clone을 derive하세요

// TODO: Article에 Summarize를 구현하세요
// summary 메서드는 "Article: {title}"을 반환해야 합니다

// TODO: 공개 filled 필드(bool)를 가진 공개 구조체 Form을 정의하세요

// TODO: Form에 Validate를 구현하세요
// validate 메서드는 filled의 값을 반환해야 합니다

fn main() {
    let mut title = String::new();
    io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();

    let mut filled_input = String::new();
    io::stdin().read_line(&mut filled_input).expect("Failed to read line");
    let filled: bool = filled_input.trim().parse().expect("Failed to parse bool");

    // TODO: 주어진 title로 Article을 생성하세요
    
    // TODO: 주어진 filled 값으로 Form을 생성하세요
    
    // TODO: article과 form으로 process_items를 호출하세요
}
quiz icon실력 점검

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

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

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