デフォルト実装のオーバーライド
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 32/61。
デフォルト実装は便利ですが、標準とは異なる振る舞いが型に必要になる場合があります。その場合は、impl ブロック内で独自の実装を提供してデフォルトをoverrideできます。
同じシグネチャでメソッドを定義し、独自のロジックを含めるだけです:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
Greet はデフォルトの greet メソッドを提供しますが、Robot はそれを独自のバージョンで完全に置き換えます。Robot に対して greet() を呼び出すと、Rust はカスタム実装を使用します:
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // ビープ・ブープ。ユニット42がオンラインです。
これにより柔軟性が得られます。default で問題ない型は何も記述する必要がありません。一方、特別な動作が必要な型は、必要な method だけを override できます。それでも trait によって、実装するすべての型でその method が利用できることが保証されます。
チャレンジ
簡単異なるアラートの種類がメッセージをカスタマイズできる通知システムを構築しましょう!デフォルト実装を持つトレイトを作成し、一方の型にはデフォルトを使用させ、もう一方にはカスタム動作でそれをオーバーライドさせます。
コードを3つのファイルに整理します。
notifiable.rs:デフォルト実装を持ち、"Alert: Something happened!"を返すnotify(&self) -> Stringメソッドを持つpublicなNotifiableトレイトをDefineします。alerts.rs:トレイトをそれぞれ異なる方法でimplementする、2つのpublicな構造体をCreateします。GenericAlert:デフォルトのnotificationを使用するunit構造体(emptyのimpl block)UrgentAlert:publicなmessageフィールド(String)を持つ構造体。デフォルトをoverrideし、{message}を返します。ここで{message}はそのstoredされたメッセージです。
main.rs:モジュールをまとめ、両方の動作を示します。提供されたinputを使ってGenericAlertとUrgentAlertをCreateし、それらのnotificationをPrintします。
ここでの重要なポイントは、GenericAlertがデフォルトから無料で動作を得る一方、UrgentAlertはimpl block内でメソッドをDefineすることで、独自の特化されたバージョンを提供するということです。
出力は次の形式に従う必要があります。
Alert: Something happened!
URGENT: {message}たとえば、inputがServer is down!の場合:
Alert: Something happened!
URGENT: Server is down!inputは1つ受け取ります。urgent alertのmessageです。
自分で試してみよう
mod notifiable;
mod alerts;
use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;
fn main() {
// 緊急アラートメッセージの入力を読み取る
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: GenericAlert インスタンスを作成する
// TODO: 入力メッセージで UrgentAlert インスタンスを作成する
// TODO: GenericAlert からの通知を出力する
// TODO: UrgentAlert からの通知を出力する
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ