3.3.3 Trait 方法冲突

03-Trait 方法冲突 — Comprehensive Rust

译文 · 基于 Comprehensive Rust

原文链接: https://google.github.io/comprehensive-rust/idiomatic/leveraging-the-type-system/extension-traits/trait-method-conflicts.html

3.3.3 Trait 方法冲突

为同一类型实现的两个不同 trait 方法发生命名冲突时会怎样?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 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());
}
  • 你正在扩展的 trait 可能在较新版本中添加与你的扩展方法同名的新 trait 方法。或者,同一类型的另一个扩展 trait 可能定义与你的扩展方法冲突的方法名。

    提问:上例会发生什么?会有编译错误吗?两个方法中哪一个优先级更高?

  • 编译器会拒绝该代码,因为它无法确定调用哪个方法。Ext1 与 Ext2 彼此没有更高优先级。

    要解决此冲突,必须指定想用哪个 trait。

    演示:改为调用 Ext1::is_palindrome("dad") 或 Ext2::is_palindrome("dad"),而不是 "dad".is_palindrome()。

    对于签名更复杂的方法,可能需要使用更显式的 完全限定语法。

  • 演示:将 "dad".is_palindrome() 替换为 <str as Ext1>::is_palindrome("dad") 或 <str as Ext2>::is_palindrome("dad")。

最后修改 August 11, 2026: 更新 (70a5af133)