ジェネリックメソッド
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 25/61。
ジェネリック構造体は任意の型を保持できますが、そのデータを操作するメソッドがなければ、あまり便利ではありません。ジェネリック構造体のメソッドを定義するには、implブロック内で特別な構文を使用する必要があります。
重要なのは、impl自体でジェネリックパラメータを宣言することです:
struct Wrapper<T> {
value: T,
}
impl<T> Wrapper<T> {
fn get(&self) -> &T {
&self.value
}
}
Wrapper<T> の前にある impl<T> に注目してください。これは、T が実装ブロック全体に対するジェネリック型パラメータであることを Rust に伝えます。この宣言がないと、Rust は T という具象型を探しますが、見つけられずに失敗します。
getメソッドは&Tを返します。これは、ラッパーが保持している任意の型への参照です。Tが整数、文字列、その他の型のいずれであっても機能します。
let num_wrapper = Wrapper { value: 100 };
let text_wrapper = Wrapper { value: "Rust" };
println!("{}", num_wrapper.get()); // 100
println!("{}", text_wrapper.get()); // Rust
ジェネリックなTがコンパイル時にそれぞれの具体的な型に適応するため、同じメソッド定義が両方に対して機能します。
チャレンジ
簡単ジェネリックコンテナをメソッド付きに拡張しましょう!任意の型を保持でき、その contents とやり取りするためのメソッドを提供する Box 構造体(Rust の標準の Box と混同しないでください)を作成します。
コードを 2 つのファイルに整理します。
mybox.rs: private な fieldcontents(型T)を持つ public な generic struct calledMyBox<T>を Define します。この struct に methods を Implement します。- given value で新しい
MyBoxを Creates するnewassociated function - contents への reference を返す(
&selfを使用)peekmethod - 新しい value を受け取り、current contents を Replace する(
&mut selfを使用)replacemethod
- given value で新しい
main.rs: module を取り込み、異なる型で generic methods が動作することを示します。box を作成し、その contents を peek し、values を replace して methods の動作を示します。
generic struct に methods を Implement するための key syntax を Remember してください。Rust に T が entire implementation block の generic parameter であることを伝えるため、MyBox<T> の前に impl<T> が必要です。
main file では、次の操作で MyBox を示します。
- integer で box を作成する(first input、
i32として parse) - その contents を peek して value を print する
- contents を新しい integer で Replace する(second input、
i32として parse) - もう一度 peek して updated value を示す
- string で second box を作成する(third input)
- string box の contents を peek する
output は次の format に従ってください。
Integer box contains: {value}
After replace: {value}
String box contains: {value}たとえば、inputs が 10、25、Rust の場合:
Integer box contains: 10
After replace: 25
String box contains: Rust3 つの inputs を受け取ります。initial integer、replacement integer、そして string value です。
自分で試してみよう
mod mybox;
use mybox::MyBox;
fn main() {
// 入力を読み取る
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let initial_int: i32 = input1.trim().parse().expect("Invalid integer");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let replacement_int: i32 = input2.trim().parse().expect("Invalid integer");
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: 初期整数で MyBox を作成する
// TODO: Peek at its contents and print: "Integer box contains: {value}"
// TODO: 内容を置換整数で置き換える
// TODO: Peek again and print: "After replace: {value}"
// TODO: 文字列値で2つ目の MyBox を作成する
// TODO: Peek at the string box and print: "String box contains: {value}"
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ