トレイト
trait は、未知の型 Self に対して定義されたメソッドの集合です。 同じトレイト内で宣言された他のメソッドにアクセスできます。
トレイトは任意のデータ型に対して実装できます。以下の例では、 メソッドのグループである Animal を定義します。その後、Animal trait を Sheep データ型に対して実装し、Sheep で Animal のメソッドを 使用できるようにします。
struct Sheep { naked: bool, name: &'static str } trait Animal { // 関連関数のシグネチャ。`Self` は実装側の型を指します。 fn new(name: &'static str) -> Self; // メソッドのシグネチャ。これらは文字列を返します。 fn name(&self) -> &'static str; fn noise(&self) -> &'static str; // トレイトはデフォルトのメソッド定義を提供できます。 fn talk(&self) { println!("{} が {} と言う", self.name(), self.noise()); } } impl Sheep { fn is_naked(&self) -> bool { self.naked } fn shear(&mut self) { if self.is_naked() { // 実装側のメソッドは、実装側のトレイトメソッドを使用できます。 println!("{} はすでに裸です...", self.name()); } else { println!("{} が毛を刈られました!", self.name); self.naked = true; } } } // `Sheep` に対して `Animal` トレイトを実装します。 impl Animal for Sheep { // `Self` は実装側の型、つまり `Sheep` です。 fn new(name: &'static str) -> Sheep { Sheep { name: name, naked: false } } fn name(&self) -> &'static str { self.name } fn noise(&self) -> &'static str { if self.is_naked() { "メェェェ?" } else { "メェェェ!" } } // デフォルトのトレイトメソッドはオーバーライドできます。 fn talk(&self) { // たとえば、少し静かな黙考を加えることができます。 println!("{} は少し間を置いた... {}", self.name, self.noise()); } } fn main() { // この場合、型アノテーションが必要です。 let mut dolly: Sheep = Animal::new("Dolly"); // TODO ^ 型アノテーションを削除してみてください。 dolly.talk(); dolly.shear(); dolly.talk(); }