Menu
Coddy logo textTech

パラメータを持つトレイト

CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 33/61。

これまで、私たちのtraitのメソッドはパラメータとして&selfだけを受け取っていました。しかし、traitのメソッドは通常のメソッドと同じように、追加のパラメータを受け取ることができます。これにより、実際の運用でより便利になります。

trait を定義するとき、メソッドシグネチャに必要なパラメータを含めることができます。

trait Calculator {
    fn add(&self, a: i32, b: i32) -> i32;
    fn multiply(&self, a: i32, b: i32) -> i32;
}

この Calculator trait には、&self に加えてそれぞれ2つの整数を受け取る2つのメソッドが必要です。この trait を実装する型は、これらの両方の操作を、これらの正確なシグネチャで提供しなければなりません。

構造体がこれを実装する方法は次のとおりです:

struct BasicCalc;

impl Calculator for BasicCalc {
    fn add(&self, a: i32, b: i32) -> i32 {
        a + b
    }
    
    fn multiply(&self, a: i32, b: i32) -> i32 {
        a * b
    }
}

これで、引数を指定してこれらのメソッドを使用できます。

let calc = BasicCalc;
println!("{}", calc.add(5, 3));       // 8
println!("{}", calc.multiply(4, 7));  // 28

トレイトは各メソッドが受け取るパラメーターを定義し、実装はそれらのパラメーターをどのように使用するかを定義します。これにより、異なる型が同じ操作をそれぞれ独自の方法で実行できます。たとえば、LoggingCalcはresultを返す前に各操作を出力できます。

challenge icon

チャレンジ

簡単

異なるプロセッサがそれぞれの方法でテキストを変換できる、文字列操作ツールキットを作ってみましょう!パラメータを受け取る methods を持つ TextProcessor trait を作成し、それを異なる two 種類のプロセッサ型に Implement します。

コードを three つのファイルに整理します。

  • processor.rs: パラメータを受け取る two つの methods を持つ public TextProcessor trait を Define します。
    • repeat(&self, text: &str, times: u32) -> String: 与えられたテキストを指定された回数繰り返します
    • truncate(&self, text: &str, max_len: usize) -> String: テキストを指定された最大長まで短縮します
  • processors.rs: trait を Implement する two つの public 構造体を Create します。
    • SimpleProcessor: 各繰り返しの間に spaces を入れてテキストを繰り返す unit 構造体です(例: "Hi" を 3 回繰り返すと "Hi Hi Hi" になります)。また、最大長の位置で単純に切り取って短縮します
    • FancyProcessor: 各繰り返しの間に " * " を入れてテキストを繰り返す unit 構造体です(例: "Hi" を 3 回繰り返すと "Hi * Hi * Hi" になります)。テキストが短縮された場合(元のテキストが max_len より長い場合のみ)、"..." を追加して短縮します
  • main.rs: モジュールをまとめ、使用するプロセッサによって同じ traitmethods が異なる results を生成することを示します。

main ファイルで両方のプロセッサを Create し、inputs を使ってテストします。three つの inputs、つまり text 文字列、repeat 回数、max length を受け取ります。

各プロセッサの動作を示す four 行を Print します。

Simple repeat: {result}
Simple truncate: {result}
Fancy repeat: {result}
Fancy truncate: {result}

たとえば、inputs が Hello34 の場合は次のようになります。

Simple repeat: Hello Hello Hello
Simple truncate: Hell
Fancy repeat: Hello * Hello * Hello
Fancy truncate: Hell...

両方のプロセッサが同じ TextProcessor の contract を満たしていますが、それぞれ独自の方法で text を transform していることに注目してください!traitwhat パラメータを methods が受け取るかを Define し、各 Implement はそれを how 使用するかを決定します。

three つの inputs、つまり処理する text、繰り返し回数(u32 として parse)、そして truncate の最大長(usize として parse)を受け取ります。

自分で試してみよう

mod processor;
mod processors;

use processor::TextProcessor;
use processors::{SimpleProcessor, FancyProcessor};

fn main() {
    // 入力を読み取る
    let mut text = String::new();
    std::io::stdin().read_line(&mut text).expect("Failed to read line");
    let text = text.trim();
    
    let mut times_input = String::new();
    std::io::stdin().read_line(&mut times_input).expect("Failed to read line");
    let times: u32 = times_input.trim().parse().expect("Failed to parse times");
    
    let mut max_len_input = String::new();
    std::io::stdin().read_line(&mut max_len_input).expect("Failed to read line");
    let max_len: usize = max_len_input.trim().parse().expect("Failed to parse max_len");
    
    // プロセッサを作成する
    let simple = SimpleProcessor;
    let fancy = FancyProcessor;
    
    // TODO: プロセッサを使ってテキストを変換し、結果を出力する
    // 次の4行を出力する:
    // Simple repeat: {result}
    // Simple truncate: {result}
    // Fancy repeat: {result}
    // Fancy truncate: {result}
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Rustオンラインコンパイラ