トレイト、プロトコル、インターフェース

// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

trait Receiver {
    fn send(&self, message: &str);
}

struct EmailAddress(String);

impl Receiver for EmailAddress {
    fn send(&self, message: &str) {
        println!("Email to {}: {}", self.0, message);
    }
}

struct ChatId {
    uuid: [u8; 16],
}

impl Receiver for ChatId {
    fn send(&self, message: &str) {
        println!("Chat message sent to {:?}: {}", self.uuid, message);
    }
}
  • Rust における多相性とジェネリクスの概念は、トレイトを中心に大きく構築されています。

  • トレイトは、ジェネリックな文脈で型に対して課される要件です。

  • 要件は、コンパイル時に検査されるダックタイピングによく似たものとして機能します。

    ダックタイピングは、Python のような動的で型なしの言語の実践に由来する 概念で、「アヒルのように歩き、アヒルのように鳴くなら、それはアヒルだ」 というものです。

    つまり、関数が期待するメソッドやフィールドを持つ型は、どれもその関数に とって有効な入力です。ある型がメソッドを実装していれば、ダックタイピングの 文脈ではその型として扱われます。

    トレイトは静的なダックタイピングの仕組みのように振る舞い、型ではなく 振る舞いを指定します。ただし、その振る舞いが本当に存在するかどうかを コンパイル時に検査できます。

  • 別の見方をすると、トレイトは命題の集まりのようなものであり、ある型に対して トレイトを実装することは、そのトレイトが要求されるあらゆる場所でその型を 使用できることの証明です。

    トレイトには必須メソッドがあり、それらのメソッドを実装することが、ある 型が必要な振る舞いを備えていることの証明になります。

参考:

  • https://doc.rust-lang.org/reference/items/traits.html