外部型の拡張

拡張トレイトとは、主な目的が外部型に新しいメソッドを追加することである、ローカルなトレイト定義です。

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

mod ext {
    pub trait StrExt {
        fn is_palindrome(&self) -> bool;
    }

    impl StrExt for str {
        fn is_palindrome(&self) -> bool {
            self.chars().eq(self.chars().rev())
        }
    }
}

fn main() {
    // 拡張トレイトをスコープに導入し...
    pub use ext::StrExt as _;
    // ...その後、それらのメソッドをあたかも固有メソッドであるかのように呼び出す
    assert!("dad".is_palindrome());
    assert!(!"grandma".is_palindrome());
}
  • Ext 接尾辞は、慣例として拡張トレイトの名前に付けられます。

    これは、そのトレイトが主に拡張の目的で使われること、したがってそれを定義している crate の外部で実装することを意図していないことを示します。

    命名規則に関する権威ある情報源として、「Extension Trait」RFC を参照してください。

  • 外部型に対する拡張トレイトの実装は、トレイト自体と同じ crate 内になければなりません。そうでないと、Rust の 孤児ルール に阻まれます。

  • 拡張トレイトのメソッドを呼び出すときは、その拡張トレイトがスコープ内になければなりません。

    対応する拡張トレイトがスコープ内にないまま拡張メソッドを呼び出そうとしたときに発生するコンパイラエラーを確認するには、例の use 文をコメントアウトしてください。

  • 上の例では、ほかにインポートされたトレイトとの名前衝突の可能性を最小限に抑えるために、アンダースコアインポートuse ext::StringExt as _)を使っています。

    アンダースコアインポートでは、そのトレイトはスコープ内にあるものと見なされ、そのトレイトを実装している型に対してそのメソッドを呼び出せます。一方、その シンボル 自体には直接アクセスできません。これにより、たとえばそのトレイトを where 句で使うことはできません。

    拡張トレイトは where 句で使うことを意図していないため、慣例としてアンダースコアインポートでインポートされます。