【问题标题】:How to move a value out of an object-safe trait object?如何将值移出对象安全的特征对象?
【发布时间】:2018-11-29 15:44:01
【问题描述】:

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`

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

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

如果这无法实现,有什么好的解决方法?

【问题讨论】:

  • 为什么是self 而不是&amp;self
  • 除了采用 take 模式之外想不出其他方法:fn take_name(&amp;mut self) -&gt; String 是对象安全的,但需要对类型的状态域进行扩展。

标签: rust traits ownership trait-objects


【解决方案1】:

正如编译器所暗示的,特征不能静态确定,因为您正在处理动态调度。在这种情况下,使用self: Box&lt;Self&gt; 仍然可以拥有所有权。

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() {}

【讨论】:

  • 非常感谢,我一直在寻找类似的东西。我想问另外一件事,如果你能帮我解决这个问题:虽然 Rust 文档通常很糟糕,但我确实搜索了很多类似的解决方案,而且我确信在 Rust by Example 中没有类似的东西、Rust Book 或 Nomicum。而且我仍然对官方参考资料中的大部分内容并不完全满意,我猜我会发现。是否有其他来源可以让我在实践中看到更高级的模式?
  • @Sam96 (1) Rust subreddit 有一些关于良好模式和技术内容的最终博客文章; (2) 官方 Zulip 和 Discord 频道是向聪明人提出复杂问题的好地方;(3) 就我个人而言,我的大部分 Rust 知识都是通过 hack 开源项目获得的
猜你喜欢
  • 1970-01-01
  • 2017-10-21
  • 2019-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
相关资源
最近更新 更多