如何将值移出对象安全的特征对象?
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
而不是&self
?
除了采用 take 模式之外想不出其他方法:fn take_name(&mut self) -> String
是对象安全的,但需要对类型的状态域进行扩展。
【参考方案1】:
正如编译器所暗示的,特征不能静态确定,因为您正在处理动态调度。在这种情况下,使用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()
【讨论】:
非常感谢,我一直在寻找类似的东西。我想问另外一件事,如果你能帮我解决这个问题:虽然 Rust 文档通常很糟糕,但我确实搜索了很多类似的解决方案,而且我确信在 Rust by Example 中没有类似的东西、Rust Book 或 Nomicum。而且我仍然对官方参考资料中的大部分内容并不完全满意,我猜我会发现。是否有其他来源可以让我在实践中看到更高级的模式? @Sam96 (1) Rust subreddit 有一些关于良好模式和技术内容的最终博客文章; (2) 官方 Zulip 和 Discord 频道是向聪明人提出复杂问题的好地方;(3) 就我个人而言,我的大部分 Rust 知识都是通过 hack 开源项目获得的以上是关于如何将值移出对象安全的特征对象?的主要内容,如果未能解决你的问题,请参考以下文章