0Pricing
Learn Rust Coding · レッスン

Rustでジェネリックコードを書く

型安全性を損なわずに再利用性を高めるため、複数の型で動作する関数とデータ構造の書き方を学びます。

「Rustでジェネリックコードを書く」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン1/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。

このレッスンの一部はまだ翻訳されておらず、英語で表示されています。

Why Write Generic Code?

Imagine you need a function that finds the largest item in a list. What if you need it for numbers, and then for characters, and then for custom objects?

Without generics, you'd write a separate function for each type, leading to lots of duplicated code. This is where generics come in!

Introducing Generics

Generics allow you to write code that works with multiple types, without repeating yourself. They are a way to write flexible and reusable functions or data structures.

Think of it as a blueprint that can be adapted for different materials.

Your First Generic Function

To make a function generic, we declare type parameters in angle brackets <> after the function name. A common type parameter name is T (for Type).

This print_anything function can now print any type!

fn print_anything<T>(item: T) {
    println!("The item is: {}", item);
}

pub fn main() {
    print_anything(5);
    print_anything("hello");
    print_anything(true);
}

Type Parameters Explained

The <T> in fn print_anything<T>(item: T) means T is a placeholder for a type. When you call the function with an i32, T becomes i32.

  • Type Parameters: Generic types are usually named with uppercase letters, like T, U, V.
  • Flexibility: The compiler figures out the concrete type at compile time.

Adding Behavior: Trait Bounds

Sometimes, your generic function needs its type parameter T to have specific behaviors. For example, if you want to compare two Ts, T must be comparable.

We add trait bounds to specify these requirements. Here, T: PartialOrd + Copy means T must implement the PartialOrd (partial ordering for comparison) and Copy traits.

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

pub fn main() {
    let number_list = vec![34, 50, 25, 100, 65];
    println!("Largest number: {}", largest(&number_list));

    let char_list = vec!['y', 'm', 'a', 'q'];
    println!("Largest char: {}", largest(&char_list));
}

Multiple Trait Bounds Syntax

You can require multiple traits for a generic type by using the + syntax, like T: TraitA + TraitB.

For complex bounds, you can also use a where clause after the function signature, which can make the signature cleaner:

fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug { /* ... */ }

Generic Structs

Just like functions, you can define structs to be generic over one or more type parameters. This allows your data structures to hold data of any specified type.

The Point<T> struct can hold coordinates of any type T (e.g., i32, f64).

struct Point<T> {
    x: T,
    y: T,
}

pub fn main() {
    let integer_point = Point {
        x: 5,
        y: 10
    };
    let float_point = Point {
        x: 1.0,
        y: 4.0
    };

    println!("Int Point: ({}, {})", 
             integer_point.x, integer_point.y);
    println!("Float Point: ({}, {})", 
             float_point.x, float_point.y);
}

Implementing Methods on Generic Structs

When implementing methods for a generic struct, you need to specify the generic type parameter(s) after impl.

You can also add trait bounds to methods if a method specifically requires certain behavior from its generic types.

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

pub fn main() {
    let p = Point {
        x: 5,
        y: 10
    };
    println!("p.x = {}", p.x());
}

Generics and Performance

One of Rust's strengths is that generics are a zero-cost abstraction. This means using generics doesn't incur any runtime performance penalty.

Rust achieves this through monomorphization: at compile time, the compiler generates specialized versions of your generic code for each concrete type it's used with. So, largest<i32> and largest<char> become two distinct, optimized functions.

Test Your Knowledge

Which of the following statements about Rust generics are TRUE?

Recap: The Power of Generics

In this lesson, you've learned the fundamentals of writing generic code in Rust:

  • What they are: A way to write flexible, reusable code.
  • Generic functions: Using <T> for type parameters.
  • Trait bounds: Specifying required behaviors with T: Trait.
  • Generic structs: Creating data structures that hold generic types.
  • Zero-cost: Rust's generics compile to specific code, ensuring no runtime penalty.

Generics are a cornerstone of idiomatic Rust, enabling powerful, type-safe abstractions!

よくある質問

「Rustでジェネリックコードを書く」レッスンは無料ですか?

はい。「Rustでジェネリックコードを書く」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。

「Rustでジェネリックコードを書く」で何を学びますか?

型安全性を損なわずに再利用性を高めるため、複数の型で動作する関数とデータ構造の書き方を学びます。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Learn Rust Codingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/3です。

「Rustでジェネリックコードを書く」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLearn Rust Codingレッスンでコードを書いて実行できますか?

はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Rustでジェネリックコードを書く
  2. トレイトの定義と実装
  3. 高度なトレイトの利用:関連型
← Learn Rust Codingに戻る