Menu
Coddy logo textTech

제네릭 구조체

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

지금까지 만든 모든 struct에는 구체적이고 명확한 type의 field가 있었습니다. Pet에는 String name이 있고, Rectangle에는 f64 dimensions가 있습니다. 하지만 any type의 data를 hold할 수 있는 struct를 만들고 싶다면 어떻게 해야 할까요?

여기서 제네릭이 사용됩니다. 제네릭을 사용하면 여러 타입에서 작동하는 유연하고 재사용 가능한 코드를 작성할 수 있습니다. 특정 타입을 하드코딩하는 대신, 일반적으로 T인 플레이스홀더를 사용하며, 이 플레이스홀더는 struct를 사용할 때 구체적인 타입으로 대체됩니다.

어떤 타입이든 담을 수 있는 간단한 래퍼 구조체입니다:

struct Wrapper<T> {
    value: T,
}

구조체 이름 뒤의 <T>는 generic type parameter를 선언합니다. 구조체 내부에서 T는 실제로 사용하게 될 type을 대신하는 역할을 합니다. 인스턴스를 생성하면 Rust가 구체적인 type을 추론합니다:

let int_wrapper = Wrapper { value: 42 };        // T는 i32
let float_wrapper = Wrapper { value: 3.14 };    // T는 f64
let text_wrapper = Wrapper { value: "hello" };  // T는 &str

이들은 각각 서로 다른 구체적인 타입인 Wrapper<i32>, Wrapper<f64>, Wrapper<&str>이지만, 모두 동일한 struct 정의를 공유합니다. 따라서 본질적으로 동일한 작업을 수행하는 IntWrapper, FloatWrapper, StringWrapper struct를 별도로 작성할 필요가 없습니다.

T라는 문자는 단지 관례일 뿐입니다("Type"의 약어). 유효한 식별자라면 무엇이든 사용할 수 있지만, T는 Rust 및 제네릭을 사용하는 대부분의 다른 언어에서 표준입니다.

challenge icon

챌린지

쉬움

모든 type의 값을 hold할 수 있는 generic container를 만들어 봅시다! generic이 코드를 유연하고 재사용 가능하게 만드는 방법을 보여 주는 Container struct를 만들 것입니다.

코드를 두 파일에 걸쳐 구성합니다:

  • container.rs: Container<T>라는 public generic struct를 Define하고, T type의 single public field item을 포함하도록 합니다. 이 container는 integer, float, string 또는 그 밖의 모든 type을 hold할 수 있어야 합니다.
  • main.rs: container module을 불러오고, 서로 다른 type의 data를 hold하는 containers를 Create하여 유연성을 보여 줍니다. 세 개의 containers를 Create하고 각각 무엇을 hold하는지 표시합니다.

main 파일에서 다음 containers를 Create합니다:

  1. integer 값을 hold하는 container (첫 번째 input을 i32로 구문 분석)
  2. float 값을 hold하는 container (두 번째 input을 f64로 구문 분석)
  3. string을 hold하는 container (세 번째 input을 String으로 유지)

출력에는 각 container의 contents가 다음 format으로 표시되어야 합니다:

Integer container: {value}
Float container: {value}
String container: {value}

예를 들어 inputs가 42, 3.14, hello인 경우:

Integer container: 42
Float container: 3.14
String container: hello

동일한 Container<T> Define이 세 가지 서로 다른 type 모두에서 작동한다는 점에 주목하세요. 이것이 바로 generics의 power입니다!

세 개의 inputs를 받습니다: integer 값, float 값, string 값입니다.

직접 해보기

mod container;

use container::Container;

fn main() {
    // 세 개의 입력을 읽기
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let int_value: i32 = input1.trim().parse().expect("Failed to parse integer");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let float_value: f64 = input2.trim().parse().expect("Failed to parse float");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let string_value = input3.trim().to_string();

    // TODO: Create three containers using Container<T>
    // 1. An integer container holding int_value
    // 2. A float container holding float_value
    // 3. A string container holding string_value

    // TODO: 각 컨테이너의 내용을 필요한 형식으로 출력
    // Integer container: {value}
    // Float container: {value}
    // String container: {value}
}
quiz icon실력 점검

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

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

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