Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Конфликты методов трейтов

Что происходит, когда возникает конфликт имён между двумя разными методами трейтов, реализованными для одного и того же типа?

// 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());
}
  • Расширяемый вами трейт в новой версии может добавить новый метод трейта с тем же именем, что и ваш метод-расширение. Или другой трейт-расширение для того же типа может определить метод, имя которого конфликтует с вашим методом-расширением.

    Спросите: что произойдёт в примере выше? Будет ли ошибка компиляции? Получит ли один из двух методов более высокий приоритет? Какой именно?

  • Компилятор отклоняет код, потому что не может определить, какой метод вызвать. Ни Ext1, ни Ext2 не имеют более высокого приоритета, чем другой.

    Чтобы устранить этот конфликт, нужно явно указать, какой трейт вы хотите использовать.

    Продемонстрируйте: вызовите 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").