如何将值移出对象安全的特征对象?

Posted

技术标签:

【中文标题】如何将值移出对象安全的特征对象?【英文标题】: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 是对象安全的,但需要对类型的状态域进行扩展。 【参考方案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 开源项目获得的

以上是关于如何将值移出对象安全的特征对象?的主要内容,如果未能解决你的问题,请参考以下文章

Python——面向对象的三特征

线程安全

面向对象的基本特征:封装

并发编程技术「技术辩证分析」在并发编程模式下进行线程安全以及活跃性问题简析

什么是线程安全?

面向对象的特征有哪些?