Dropトレイト
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 56/61。
Rust で値がスコープ外に出ると、automatically クリーンアップされます。しかし、そのタイミングでログの記録、リソースの解放、最後のメッセージの送信など、カスタムコードを実行する必要がある場合はどうすればよいでしょうか? Drop トレイトを使うと、構造体が破棄される直前に何が起こるかを正確に定義できます。
Drop trait には、&mut self を受け取る drop という単一の method があります。
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 が automatically 管理できないリソースを解放するといったクリーンアップ作業に使用されます。Drop トレイトにより、早期リターンによってスコープが終了した場合でも、クリーンアップコードが実行されることが保証されます。
チャレンジ
簡単自動クリーンアップを実演するリソース管理システムを構築しましょう!file の opening と closing をシミュレートする FileHandle struct を作成します。handle がスコープ外に出ると、file が closed されたことを自動的に通知します。
コードを2つの file に分けて整理します。
file_handle.rs: public なFileHandlestruct と public なfilenamefield(String)を Define します。FileHandle を Create し、file が「opened」されたときに message を prints するnewassociated function を Implement します。次にDroptrait を Implement し、handle が dropped されたときに closing message を prints します。main.rs: file_handle module を取り込み、filename を受け取り、local scope Inside に FileHandle を Create し、file が「open」の間に processing message を prints する function calledprocess_fileを作成します。Drop の Implement は scope が ends したときに automatically 実行されます。この function を provided input で呼び出します。
FileHandle が Create されたとき、次を prints する必要があります。
Opening file: {filename}processing 中(scope Inside)には、次を prints します。
Processing {filename}...FileHandle が dropped されたとき(scope ends)、次を prints する必要があります。
Closing file: {filename}たとえば、input が data.txt の場合:
Opening file: data.txt
Processing data.txt...
Closing file: data.txtinput が config.json の場合:
Opening file: config.json
Processing config.json...
Closing file: config.json1つの input、つまり filename string を受け取ります。
REQUIRED OUTPUT FORMAT:
自分で試してみよう
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);
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ