Почему связанный тип не разрешен в этом случае?

#rust

Вопрос:

 trait Envs {
    type Item;
    type Iter: Iterator;
    fn get_envs(amp;self) -> Self::Iter<Item=Self::Item>;
}
 

Я пытаюсь реализовать метод, который возвращает переменные среды, но я не мог понять, почему связанный тип не разрешен в черте.

Ответ №1:

 trait Envs {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
    fn get_envs(amp;self) -> Self::Iter;
}
 

Ссылка на игровую площадку

Если вы сделаете, как указано выше, это ограничит реализацию признака, чтобы указать Iterator , с которым связан тип, такой же, как Envs::Item . Итак, Envs::Item должно быть так же, как <Envs::Iter as Iterator>::Item .


Если вам действительно нравится:

 trait Envs {
    type Item;
    type Iter: Iterator;
    fn get_envs(amp;self) -> Self::Iter;
}
 

Это позволило бы разработчику указать Iter , который не возвращает элементы, такие же, как Envs::Item . Итак, в данном случае вполне возможно, что Envs::Item это было i32 , но Envs::Iter это Iterator конец String .

Комментарии:

1. Существует также возможность сделать только метод зависящим от дополнительных требований: fn get_envs(amp;self) -> Self::Iter where Self::Iter: Iterator<Item = Self::Item>; . (Не очень полезно в этом случае, но полезно, когда к одному методу предъявляются более высокие требования, чем к остальной части признака, и признак можно использовать без него.)

2. Еще один вариант-не беспокоиться об объявлении Item в качестве связанного типа, а просто объявить type Iter: Iterator; . Вы все еще можете получить доступ к типу элемента, используя Self::Iter::Item , если вам это нужно.

Ответ №2:

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

 trait Envs {
    type Item;
    fn get_envs(amp;self) -> Box<dyn Iterator<Item=amp;Self::Item>>;
}