Dropトレイト
CoddyのRustジャーニー「Object Oriented Programming」セクションの一部 — レッスン 56/61。
Rustで値がスコープを外れると、自動的にクリーンアップされます。しかし、その瞬間にカスタムコードを実行する必要がある場合はどうすればよいでしょうか。例えば、ロギング、リソースの解放、あるいは最後のメッセージの送信などです。Dropトレイトを使用すると、構造体が破棄される直前に何が起こるかを正確に定義できます。
Dropトレイトには、&mut selfを引数に取るdropという名前のメソッドが1つだけあります:
struct Connection {
id: u32,
}
impl Drop for Connection {
fn drop(&mut self) {
println!("Connection {} closed.", self.id);
}
}
dropを直接呼び出すことはありません。値がスコープを抜けるときに、Rustが自動的にそれを呼び出します。
fn main() {
let conn = Connection { id: 42 };
println!("Using connection...");
} // ここで自動的に "Connection 42 closed." と表示されます
出力は次のようになります:
Using connection...
Connection 42 closed.
これはRust版のデストラクタです。ファイルハンドルのクローズ、サーバーからの切断、またはRustが自動的に管理できないリソースの解放といったクリーンアップタスクに一般的に使用されます。Dropトレイトは、早期リターンによってスコープが終了した場合でも、クリーンアップコードが実行されることを保証します。
チャレンジ
簡単自動クリーンアップを実証するリソース管理システムを構築しましょう!ファイルを開いたり閉じたりすることをシミュレートする FileHandle 構造体を作成します。ハンドルがスコープ外に出ると、ファイルが閉じられたことを自動的に通知します。
コードを2つのファイルに分けて構成します:
file_handle.rs: 公開されたfilenameフィールド(String)を持つ公開FileHandle構造体を定義します。FileHandle を作成し、ファイルが "opened"(開かれた)ときにメッセージを表示するnew関連関数を実装します。次に、ハンドルがドロップされたときに終了メッセージを表示するようにDropトレイトを実装します。main.rs: file_handle モジュールを取り込み、ファイル名を受け取り、ローカルスコープ内で FileHandle を作成し、ファイルが "open"(開いている)間に処理メッセージを表示するprocess_fileという関数を作成します。スコープが終了すると、Drop の実装が自動的に実行されます。提供された入力を使用してこの関数を呼び出します。
FileHandle が作成されるとき、次のように表示する必要があります:
Opening file: {filename}処理中(スコープ内)は、次のように表示します:
Processing {filename}...FileHandle がドロップされる(スコープが終了する)とき、次のように表示する必要があります:
Closing file: {filename}例えば、入力が data.txt の場合:
Opening file: data.txt
Processing data.txt...
Closing file: data.txt入力が config.json の場合:
Opening file: config.json
Processing config.json...
Closing file: config.json1つの入力(ファイル名の文字列)を受け取ります。
チートシート
Dropトレイトを使用すると、値がスコープを抜けるときに自動的に実行されるカスタムのクリーンアップコードを定義できます。
Dropトレイトは、&mut selfを引数に取るdropという名前の単一のメソッドを持っています。
struct Connection {
id: u32,
}
impl Drop for Connection {
fn drop(&mut self) {
println!("Connection {} closed.", self.id);
}
}
dropを直接呼び出すことはありません。値がスコープを抜けるときに、Rustが自動的に呼び出します。
fn main() {
let conn = Connection { id: 42 };
println!("Using connection...");
} // ここで自動的に "Connection 42 closed." と表示されます
Dropトレイトは、ファイルハンドルのクローズ、サーバーからの切断、リソースの解放といったクリーンアップタスクによく使用されます。早期リターンによってスコープが終了した場合でも、クリーンアップコードが実行されることを保証します。
自分で試してみよう
mod file_handle;
use file_handle::FileHandle;
// TODO: process_file 関数を実装する
// 以下の手順で行います:
// 1. ローカルスコープを作成する(波括弧 {} を使用)
// 2. そのスコープ内で、FileHandle::new() を使用して FileHandle を作成する
// 3. 処理メッセージ "Processing {filename}..." を表示する
// 4. スコープが終了すると、Drop が自動的に呼び出される
fn process_file(filename: &str) {
// TODO: この関数を実装する
}
fn main() {
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let filename = input.trim();
process_file(filename);
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。