Возврат ссылки на ящик - PullRequest
0 голосов
/ 19 апреля 2020

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

trait Animal {}

struct Dog {}
impl Dog for Animal{}

struct Cat{}
impl Cat for Animal{}

вместе с контейнером, который содержит несколько вариантов animal:

struct Person {
  my_dog: Dog,
  my_cat: Cat
}

Что я хочу сделать, это написать помощник, который ищет соответствующее животное, как это:

impl Person {
  fn look_up_animal(&self, animal_name: &str) -> Box<&dyn Animal> {
    match animal_name {
      "dog" => Box::from(&self.my_dog),
      "cat" => Box::from(&self.my_cat)
    }
  }
}

К сожалению, я не могу понять, как сделать типы для этого. В приведенной выше версии с использованием ссылок и Box выдается ошибка типа «ожидается struct Box<&dyn Animal>, но получено struct Box<&Dog>», поэтому я не совсем уверен, как преобразовать обычное значение в значение dyn.

Ответы [ 2 ]

5 голосов
/ 19 апреля 2020

Полностью явной версией того, что вы хотите, будет

impl Person {
    fn look_up_animal(&self, animal_name: &str) -> Option<Box<&dyn Animal>> {
        match animal_name {
            "dog" => Some(Box::from(&self.my_dog as &dyn Animal)),
            "cat" => Some(Box::from(&self.my_cat as &dyn Animal)),
            _ => None,
        }
    }
}

Rust способен принудительно ссылаться на один слой ссылок на объекты признаков, но два слоя ссылок (оба Box и &) спотыкается. (Наличие ссылки внутри Box также вызывает предупреждение clippy.) Это предлагает другое решение.

impl Person {
    fn look_up_animal(&self, animal_name: &str) -> Option<&dyn Animal> {
        match animal_name {
            "dog" => Some(&self.my_dog as &dyn Animal),
            "cat" => Some(&self.my_cat as &dyn Animal),
            _ => None,
        }
    }
}

На этот раз явное приведение as &dyn Animal не требуется, поскольку существует только один слой ссылки.

impl Person {
    fn look_up_animal(&self, animal_name: &str) -> Option<&dyn Animal> {
        match animal_name {
            "dog" => Some(&self.my_dog),
            "cat" => Some(&self.my_cat),
            _ => None,
        }
    }
}

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


Примечание: я добавил в Option, чтобы было что возвращать, когда animal_name нет 't "dog" или "cat". Вы также можете использовать pani c или по умолчанию что-то еще, что реализует Animal.

0 голосов
/ 19 апреля 2020
trait Animal {}

struct Dog {}
impl Animal for Dog{}

struct Cat{}
impl Animal for Cat{}

Полное решение детская площадка

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