9

AMech携带一个驱动程序,它是一个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将所有权返回给 a String,以便在链式调用中进一步使用它(在实际代码中它是 a 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;
}

↓</p>

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`

有没有办法让这种模式发生?

我似乎缺少什么基本的东西吗?

如果这是不可能实现的,有什么好的方法可以解决它?

4

1 回答 1

13

正如编译器所暗示的那样,由于您正在处理动态调度,因此无法静态确定特征。在这种情况下,使用self: 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() {}
于 2018-06-20T13:57:59.817 回答