Различия между 2 стилями реализаций по умолчанию в черте? - PullRequest
0 голосов
/ 25 января 2019

Существует два способа предоставления методов для самой Черты, Rustdoc различает их, говоря «предоставленные методы» и impl dyn XXX.Например:

trait Trait {
    fn foo(&self) {
        println!("Default implementation");
    }
}

impl Trait {
    fn bar(&self) {
        println!("Anonymous implementation?");
    }
}

Я заметил это, когда читал документацию Rust's failure ящик.

Каковы варианты использования для них?В чем различия?

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Первый фрагмент,

trait Trait {
    fn foo(&self) {
        println!("Default implementation");
    }
}

реализует предоставленный метод для черты.Этот метод может быть переопределен реализацией черты, но он не должен быть переопределен.

Второй фрагмент,

impl Trait {
    fn bar(&self) {
        println!("Anonymous implementation?");
    }
}

реализует свойственный метод на объект черты типа dyn Trait.Реализации методов для dyn Trait можно вызывать только для объектов признаков, например, типа &dyn Trait.Они не могут получить self по значению, поскольку dyn Trait не имеет размера, известного во время компиляции, и они не могут быть вызваны для конкретных типов , реализующих Trait (включая обобщенные типы с ограничением Trait).

В современной нотации пишется impl dyn Trait вместо impl Trait, и фактически эта нотация была одним из мотивирующих примеров длявведение ключевого слова dyn - старый синтаксис не давал никаких подсказок о том, что такое семантика, тогда как новый синтаксис с ключевым словом dyn намекает на то, что этот impl используется только вместе с динамической диспетчеризацией.

Объект признака - это толстый указатель на объект, реализующий Trait, но конкретный тип объекта не обязательно известен во время компиляции.Толстый указатель содержит указатель на данные объекта, а также указатель на таблицу виртуальных методов типа объекта.Последний используется для динамической отправки к правильной реализации черты во время выполнения.

Довольно редко используется impl dyn Trait.Как правило, это полезно, только если вы хотите использовать некоторую информацию о динамическом типе, например, понижение до реального типа.Единственные черты с внутренними методами для объектов черт в стандартной библиотеке: Any и Error.

0 голосов
/ 25 января 2019

Короче говоря: один может быть переопределен, а другой нет.

Когда вы определяете черту, вы определяете элементы, которые реализации (или должны) реализации черты могут переопределять:

trait Trait {
    fn foo(&self) {
        println!("Default implementation");
    }
}

impl Trait for i64 {
    fn foo(&self) {
        println!("i64 implementation: {}", self);
    }
}

С другой стороны, используя impl Trait, вы определяете присущие методы, которые нельзя переопределить:

impl Trait {
    fn bar(&self) {
        self.foo();
        self.foo()
    }
}

// Try:
impl Trait for i64 {
    fn bar(&self) { ... } // error: bar cannot be overridden.
}

В результате методы встроенных признаков действуют как Шаблонный шаблонный метод : они обеспечивают холст, связывающий вместе один или несколько переопределяемых методов.

Если вы посмотрите на failure ящик, который вы связали, метод Failure::find_root_cause() гласит:

Это эквивалентно итерации по iter_causes() и получению последнего элемента.

Вы можете рассматривать эти присущие методы как удобные методы , методы, обеспечивающие простой / интуитивно понятный интерфейс для общих задач, которые могут выполняться вручную ... но удобно предопределены .

Примечание: любой встроенный метод может быть реализован как свободная функция, принимающая черту в качестве первого аргумента; однако свободные функции нельзя вызывать в позиции метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...