9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rustのtrait(トレイト)について

Posted at

トレイトとは

トレイトとは任意の型であるSelfに対してメソッドを定義でき、共通の振る舞いを実装できる機能です。

トレイトは「任意の型=あらゆるデータ型」に実装することができ、多言語のインターフェースや抽象クラスのような役割を果たします。

使い方

※ここではRust By Exampleからコードを引用し、解説を加えます。

トレイト定義
// Animalというトレイトを定義します
trait Animal {
    // スタティックメソッド(コンストラクタ)のシグネチャ。 `Self` はこのトレイトを実装している型になる。
    fn new(name: &'static str) -> Self;

    // インスタンスメソッドのシグネチャ。これらの関数は文字列を返す。
    fn name(&self) -> &'static str;
    fn noise(&self) -> &'static str;

    // メソッドのデフォルトの挙動を定義することもできる。(もちろんしなくても良い)
    fn talk(&self) {
        println!("{} says {}", self.name(), self.noise());
    }
}
トレイトを型に実装
struct Sheep { naked: bool, name: &'static str }

// 上で定義した`Animal`というトレイトを`Sheep`に実装する。
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() {
            "baaaaah?"
        } else {
            "baaaaah!"
        }
    }
    
    // デフォルトのトレイトメソッドはオーバーライドすることができる。
    fn talk(&self) {
        // 例えば、静かに熟考させてみる。
        println!("{} pauses briefly... {}", self.name, self.noise());
    }
}

fn main() {
    // この場合、型アノテーションが必須。
    let mut dolly: Sheep = Animal::new("Dolly");

    dolly.talk();
}

実行結果
Dolly pauses briefly... baaaaah!

トレイトの実装に成功しました。

次に、トレイトメソッドは任意の型のトレイトメソッドでないメソッドからでも呼び出せます。

impl Sheep {
    fn is_naked(&self) -> bool {
        self.naked
    }

    fn shear(&mut self) {
        if self.is_naked() {
            // メソッドをある型に実装する際に、その型のトレイトメソッドを
            // 使用することができる。
            println!("{} is already naked...", self.name());
        } else {
            println!("{} gets a haircut!", self.name);

            self.naked = true;
        }
    }
}

fn main() {
    let mut dolly: Sheep = Animal::new("Dolly");

    dolly.talk();
    dolly.shear();
    dolly.talk();
    dolly.shear();
}
実行結果
Dolly pauses briefly... baaaaah!
Dolly gets a haircut!
Dolly pauses briefly... baaaaah?
Dolly is already naked...

ここで、is_naked()やshare()を上記のimpl Animal for Sheep {}に追加すればいいと思った人もいるかもしれませんが、

これらはAnimalのトレイトメソッドではないためコンパイルエラーが起こります。

  Compiling playground v0.0.1 (/playground)
error[E0407]: method `is_naked` is not a member of trait `Animal`
  --> src/main.rs:49:5

以上になります。

今回Rust by Example(RBE)を参考にしたのですが、補足を自分なりに少し加えただけになっています。

気にされる方がいましたらこちらの記事は無視していただけると幸いです。

今後、トレイト境界やサブトレイトについても追記予定です。

参考記事

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?