デフォルト実装
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 31/61。
これまでに定義したすべてのtraitメソッドは、シグネチャだけでした。つまり、本体のない要件です。しかし、traitを実装するほとんどの型が同じロジックを使うとしたらどうでしょうか?Rustでは、traitの定義内でデフォルト実装を直接提供できます。
メソッドのシグネチャをセミコロンで終える代わりに、本文を追加します。
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
これで、implブロック内にコードを書かなくても、Greetを実装するすべての型がこのメソッドを自動的に取得します。
struct Guest;
impl Greet for Guest {}
let visitor = Guest;
println!("{}", visitor.greet()); // こんにちは!
空の impl Greet for Guest {} が有効なのは、trait がすでに動作を提供しているためです。この struct は単に trait に「参加」し、デフォルトの method をそのまま受け取ります。
このパターンは、ほとんどのケースで機能する共有の動作を Define したい場合に便利です。異なるものが必要な型は default をオーバーライドできます(これは次に学びます)が、標準的な動作で問題ない型は同じことを繰り返す必要がありません。
チャレンジ
簡単デフォルト実装の力を活用して、通知システムを構築してみましょう!標準的な動作を最初から提供するトレイトを作成するので、型は繰り返しコードを書くことなく、その動作を利用できます。
コードを3つのファイルに整理します。
notifiable.rs:notify(&self) -> Stringメソッドを持つ公開Notifiableトレイトを定義します。このメソッドにはデフォルト実装があります。デフォルトでは"You have a new notification!"を返します。このトレイトを実装する型は、implブロックに何も記述しなくても、この動作を自動的に受け取ります。alerts.rs:トレイトを実装する、2つのシンプルな公開ユニット構造体を作成します。EmailAlert:空のimplブロックでNotifiableを実装します(デフォルトを使用)SystemAlert:こちらも空のimplブロックでNotifiableを実装します(デフォルトを使用)
main.rs:モジュールをまとめ、両方のアラート型が同じデフォルト動作を共有することを示します。両方の構造体のインスタンスを作成し、それぞれのnotifyメソッドを呼び出します。
mainファイルでEmailAlertとSystemAlertを作成し、それぞれの通知を別々の行に出力します。
出力は次のようになります。
You have a new notification!
You have a new notification!両方の型が同一の出力を生成していることに注目してください。これがデフォルト実装の素晴らしいところです!どちらの構造体もnotifyメソッドのコードを書く必要がありませんでしたが、どちらも完全に機能する通知動作を備えています。次のレッスンでは、型にカスタム動作が必要な場合に、これらのデフォルトをオーバーライドする方法を学びます。
自分で試してみよう
mod notifiable;
mod alerts;
use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};
fn main() {
// TODO: EmailAlert のインスタンスを作成する
// TODO: SystemAlert のインスタンスを作成する
// TODO: Print the notification from EmailAlert
// TODO: Print the notification from SystemAlert
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ