Почему Rust согласен с принятием другой структуры при реализации той же черты? - PullRequest
0 голосов
/ 22 октября 2019

У меня есть следующее в моих тестах, которое компилируется и работает хорошо:

#[test]
fn zoo_test() {
    let mut zoo = Zoo::new();

    zoo.add(Monkey::new("m1".to_string()));
    zoo.add(Limur::new("l1".to_string()));

    assert_eq!(zoo.hi_all::<Monkey>(), vec![
        "Monkey m1 says: ah ah ah".to_string(),
        "Limur l1 says: yo".to_string()
    ]);
}

Тем не менее, я немного запутался, почему zoo.hi_all::<Monkey>() работает, так как это может быть или monkey или limur . Другими словами, я не понимаю, почему это работает для limur, или я делаю это неправильно?

Редактировать: Вот код, который я использую для src/zoo.rs:

pub mod animal;
pub mod monkey;
pub mod limur;

use std::collections::VecDeque;
use animal::Animal;

pub struct Zoo<'a> {
    list: VecDeque<Box<dyn Animal + 'a>>,
}

impl<'a> Zoo<'a> {
    pub fn new() -> Zoo<'a> {
        Zoo {
            list: VecDeque::new(),
        }
    }

    pub fn add<T>(&mut self, animal: T)
    where
        T: Animal + 'a,
    {
        self.list.push_back(Box::new(animal));
    }

    pub fn hi_all<T>(&self) -> Vec<String>
    where
        T: Animal + 'a,
    {
        let mut hi: Vec<String> = vec![];
        for animal in &self.list {
            if let Some(what) = animal.says() {
                hi.push(what);
            }
        }
        hi
    }
}

1 Ответ

3 голосов
/ 22 октября 2019

Переменная типа T объявлена ​​в типе этой функции:

pub fn hi_all<T>(&self) -> Vec<String>
where
    T: Animal + 'a,
{
    let mut hi: Vec<String> = vec![];
    for animal in &self.list {
        if let Some(what) = animal.says() {
            hi.push(what);
        }
    }
    hi
}

, но фактически никогда не используется в теле функции! Удаление этого ограничения не окажет никакого влияния, поскольку в функции не упоминается переменная типа T.

Фактически, она никогда не может использоваться *1009* любым практическим способом, потому что элементыVecDeque относятся к конкретному конкретному типу, Box<dyn Animal>, тогда как с точки зрения кода внутри функции T может быть любого типа, который реализует Animal.

* 1017. * Если вам нужно отфильтровать животных по типу , тогда я предлагаю вам использовать перечисление вместо черт объектов, чтобы вы могли различать варианты перечисления.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...