Как вывести значение из объектно-безопасного объекта черты?

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

trait Named {
    fn name(self) -> String;
}

struct Person {
    first_name: String,
    last_name: String
}

impl Named for Person {
    fn name(self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

pub struct Mech<'a> {
    driver: Box<Named + 'a>,
}

impl<'a> Mech<'a> {
    pub fn driver_name(self) -> String {
        self.driver.name()
    }
}

метод driver_name возвращает право собственности на Stringдля дальнейшего использования в цепочечных вызовах (в реальном коде это Command). Это не в состоянии компиляции с:

error[E0161]: cannot move a value of type Named + 'a: the size of Named + 'a cannot be statically determined
  --> src/lib.rs:22:9
   |
22 |         self.driver.name()
   |         ^^^^^^^^^^^

Создание черты Sized Сбой объекта безопасности:

trait Named: Sized {
    fn name(self) -> String;
}

error[E0038]: the trait `Named` cannot be made into an object
  --> src/lib.rs:17:5
   |
17 |     driver: Box<Named + 'a>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Named` cannot be made into an object
   |
   = note: the trait cannot require that `Self : Sized`

Есть ли способ заставить этот шаблон произойти?

Есть ли что-то фундаментальное, чего я, кажется, упускаю?

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

1 ответ

Решение

Как намекнул компилятор, черта не может быть определена статически, потому что вы имеете дело с динамической диспетчеризацией. В этом сценарии по-прежнему возможно владение Box<Self>:

trait Named {
    fn name(self: Box<Self>) -> String;
}

struct Person {
    first_name: String,
    last_name: String,
}

impl Named for Person {
    fn name(self: Box<Self>) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

pub struct Mech<'a> {
    driver: Box<Named + 'a>,
}

impl<'a> Mech<'a> {
    pub fn driver_name(self) -> String {
        self.driver.name()
    }
}

fn main() {}
Другие вопросы по тегам