パラメータを持つトレイト
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を返す前に各操作を出力できます。
チャレンジ
簡単異なるプロセッサがそれぞれの方法でテキストを変換できる、文字列操作ツールキットを作ってみましょう!パラメータを受け取る methods を持つ TextProcessor trait を作成し、それを異なる two 種類のプロセッサ型に Implement します。
コードを three つのファイルに整理します。
processor.rs: パラメータを受け取る two つのmethodsを持つ publicTextProcessortraitを 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: モジュールをまとめ、使用するプロセッサによって同じtraitのmethodsが異なる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 が Hello、3、4 の場合は次のようになります。
Simple repeat: Hello Hello Hello
Simple truncate: Hell
Fancy repeat: Hello * Hello * Hello
Fancy truncate: Hell...両方のプロセッサが同じ TextProcessor の contract を満たしていますが、それぞれ独自の方法で text を transform していることに注目してください!trait は what パラメータを 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}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ