В чем преимущество публикации конкретного типа в API ящика вместо `impl trait`? - PullRequest
0 голосов
/ 29 августа 2018

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

Зачем это? Более конкретно, если реализует тип, совместимый с std::env::Args, каковы плюсы и минусы использования ...

// implement iterator compatible with std::env::Args
pub struct Args { // public
    // pub(crate) ...
}

impl Iterator for Args {
    // ...
}

pub fn args() -> Args {
    // ...
    // return Args
}

против

// implement iterator compatible with std::env::Args
pub(crate) struct Args { // hidden (outside of crate)
    // pub(crate) ...
}

impl Iterator for Args {
    // ...
}

pub fn args() -> impl Iterator<Item = String> {
    // ...
    // return Args
}

1 Ответ

0 голосов
/ 29 августа 2018

Никогда не бывает единственно правильной практики.

Причины возврата конкретного типа включают в себя:

  1. В настоящее время вы не можете объявить переменную типа impl Trait, поэтому любое такое использование должно быть выведено. Они не могут быть легко помещены в структуру по той же причине.

  2. Вы не можете добавить внутренние методы к типу возврата impl Trait. Например, Chars имеет метод as_str.

  3. Поскольку trentcl указывает , impl Trait не может условно реализовать черту. Это важно для адаптеров итераторов, таких как Skip.

  4. Вы заявляете, что «совместимы с std::env::Args», но вот черты, которые Args реализует:

    impl Iterator for Args {}
    impl ExactSizeIterator for Args {}
    impl DoubleEndedIterator for Args {}
    impl Debug for Args {}
    

    Ваш интерфейс не позволяет использовать 3 из четырех. Потребители вашего API больше не могут выполнять итерации, как один из примеров. Вы можете исправить это, выполнив impl Iterator<Item = String> + DoubleEndedIterator + ExactSizeIterator + Debug, но в какой-то момент у вас все равно будет собственный тип. Эта проблема также возможна, если вы возвращаете новый тип поверх существующего итератора, поэтому мне нужен лучший синтаксис делегирования.

См. Также руководство по API C-NEWTYPE-HIDE .

стандартная библиотека Rust делает это для всех своих итераторов

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

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