トレイトメソッドの衝突

同じ型に実装された 2 つの異なるトレイトメソッドの間で名前の衝突が起きると、どうなるでしょうか?

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

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

    pub trait Ext2 {
        fn is_palindrome(&self) -> bool;
    }

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

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

pub use ext::{Ext1, Ext2};

// どのメソッドが呼び出されるでしょうか?
// `Ext1` のもの? それとも `Ext2` のもの?
fn main() {
    assert!("dad".is_palindrome());
}
  • 拡張しているトレイトが、新しいバージョンで、あなたの拡張メソッドと同じ名前の新しいトレイトメソッドを追加する可能性があります。あるいは、同じ型に対する別の拡張トレイトが、あなた自身の拡張メソッドと名前が衝突するメソッドを定義する可能性があります。

    問いかけ: 上の例では何が起こるでしょうか? コンパイラエラーになるでしょうか? 2 つのメソッドのどちらかにより高い優先順位が与えられるでしょうか? それはどちらでしょうか?

  • コンパイラは、どのメソッドを呼び出すべきか判断できないため、このコードを拒否します。Ext1 にも Ext2 にも、もう一方より高い優先順位はありません。

    この衝突を解決するには、どのトレイトを使いたいのかを明示する必要があります。

    実演: "dad".is_palindrome() の代わりに、Ext1::is_palindrome("dad") または Ext2::is_palindrome("dad") を呼び出します。

    シグネチャがより複雑なメソッドでは、より明示的な 完全修飾構文 を使う必要がある場合があります。

  • 実演: "dad".is_palindrome()<str as Ext1>::is_palindrome("dad") または <str as Ext2>::is_palindrome("dad") に置き換えます。