0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Effective-Rustlings-jp】Day 12:デフォルト実装を用いて、実装しなければならないトレイトメソッドを最小限にしよう

Last updated at Posted at 2025-01-15

はじめに

こんにちは。細々とプログラミングをしているsotanengelです。
この記事は以下の記事の連載です。

他の連載記事 (詳細)

また本記事はEffective Rust(David Drysdale (著), 中田 秀基 (翻訳))を参考に作成されております。とてもいい書籍ですので興味を持った方は、ぜひ読んでみてください!

今日の内容

概要

Rustでトレイトを実装する際には、必須メソッドデフォルト実装を定義することができます。
幅広い人々に使ってもらえるようにトレイト設計時に考慮するべきことを学びましょう。

必須メソッドとデフォルト実装を自作のトレイトに実装しよう

問(リンク)

自作のMyTraitトレイトにrequired_methodという必須メソッドを実装し、デフォルト実装のdefault_methodをオーバーライドしてください。

コード (詳細)
// MyTrait トレイトの定義
trait MyTrait {
    // TODO: required_methodという必須メソッドを作成してください。
    //       引数は&selfとしてください。

    fn default_method(&self) {
        println!("default_method: これはトレイトで定義されたデフォルト実装です。");
    }

    fn default_method_with_return(&self) -> i32 {
        println!("default_method_with_return: これはトレイトで定義されたデフォルト実装です。");
        42
    }
}

// トレイトを実装する構造体
struct MyStruct {
    pub name: String,
}

// MyStruct における MyTrait の実装
impl MyTrait for MyStruct {
    // required_method はトレイトで必須とされているので、必ず定義が必要
    fn required_method(&self) {
        println!("required_method: Hello, my name is {}!", self.name);
    }

    // default_method はデフォルトメソッドだが、ここでは独自実装でオーバーライド
    // TODO: default_methodをオーバーライドしてください。
    //       「default_method (override): 構造体 MyStruct 独自の実装です。オーバーライドされました。」という出力をしてください。
    fn default_method(&self) {}
}

fn main() {
    let my_struct = MyStruct {
        name: String::from("Alice"),
    };

    // 【必須メソッド】呼び出し
    my_struct.required_method();

    // 【デフォルトメソッド(オーバーライド済)】呼び出し
    my_struct.default_method();

    // 【デフォルトメソッド(戻り値あり)】デフォルトの実装を呼び出し
    let result = my_struct.default_method_with_return();
    println!("default_method_with_return の戻り値: {}", result);
}

解答(リンク)

コード参照。

このように「必要最小限の必須メソッド」と「多数のデフォルト実装」というトレイトを実装することで、

  • トレイトの実装者:少ないコーディングでトレイトを適用できる
  • トレイトの使用者:様々なメソッド(デフォルト実装)を利用できる

を両立することができます。

また、このような実装にすることでトレイトに機能を追加した場合でもメソッドを安全に追加することができるため、トレイトの後方互換性を保証しやすくなります。

コード (詳細)
// MyTrait トレイトの定義
trait MyTrait {
    // 【必須メソッド】
    // トレイトを実装する型は、このメソッドを必ず定義しなければなりません。
    fn required_method(&self);

    // 【デフォルトメソッド】
    // 必須ではありません。必要に応じてオーバーライドできます。
    fn default_method(&self) {
        println!("default_method: これはトレイトで定義されたデフォルト実装です。");
    }

    // 【デフォルトメソッド(戻り値あり)】
    // 必須ではありません。必要に応じてオーバーライドできます。
    fn default_method_with_return(&self) -> i32 {
        println!("default_method_with_return: これはトレイトで定義されたデフォルト実装です。");
        42
    }
}

// トレイトを実装する構造体
struct MyStruct {
    pub name: String,
}

// MyStruct における MyTrait の実装
impl MyTrait for MyStruct {
    // required_method はトレイトで必須とされているので、必ず定義が必要
    fn required_method(&self) {
        println!("required_method: Hello, my name is {}!", self.name);
    }

    // default_method はデフォルトメソッドだが、ここでは独自実装でオーバーライド
    fn default_method(&self) {
        println!(
            "default_method (override): 構造体 {} 独自の実装です。オーバーライドされました。",
            self.name
        );
    }

    // default_method_with_return はデフォルト実装のまま使いたい場合は定義不要。
}

fn main() {
    let my_struct = MyStruct {
        name: String::from("Alice"),
    };

    // 【必須メソッド】呼び出し
    my_struct.required_method();

    // 【デフォルトメソッド(オーバーライド済)】呼び出し
    my_struct.default_method();

    // 【デフォルトメソッド(戻り値あり)】デフォルトの実装を呼び出し
    let result = my_struct.default_method_with_return();
    println!("default_method_with_return の戻り値: {}", result);
}

さいごに

もしも本リポジトリで不備などあれば、リポジトリのissueやPRなどでご指摘いただければと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?