我是 Rust 的新手,我想实现一个结构,该结构可以具有不同的结构,这些结构将共同特征实现为字段
在带有垃圾收集器的传统编程语言中,我会这样实现它:
pub struct MemoryMapper {
regions: Vec<Region>,
}
trait MemoryMappable: Sized {
}
pub struct Region {
device: dyn MemoryMappable,
start: u32,
end: u32,
remap: bool
}
但是我这里有如下编译错误:
the size for values of type `(dyn MemoryMappable + 'static)` cannot be known at compilation time
the trait `Sized` is not implemented for `(dyn MemoryMappable + 'static)`
only the last field of a struct may have a dynamically sized type
change the field's type to have a statically known size
我已经尝试使 Sized 成为 MemoryMappable 的超特性,但它仍然给我以下代码带来问题:
pub fn map(&mut self, device: dyn MemoryMappable, start: u32, end: u32, remap: bool) -> &Region {
self.regions.insert(0, Region{device, start, end, remap});
return self.regions.get(0).unwrap();
}
the trait `MemoryMappable` cannot be made into an object
`MemoryMappable` cannot be made into an object
因为来自关于对象安全的 Rust 文档
Sized 不能是一个超特质。换句话说,它不能要求 Self: Sized。
我现在不知道该怎么做
结构的字段存在于堆栈中,因此在编译时必须具有已知大小。这就是 Sized
错误的意思。
dyn Trait
是“实现 Trait
的任何类型。那么它的大小是多少?好吧,这取决于底层类型是什么。
因此,dyn Trait
永远不会实现 Sized
,即使 Trait
具有 Sized
作为超特征(所有这一切都是为了保证任何实现 Trait
的类型也实现 Sized
,但您仍然不知道它是哪个)。
事实上,使 Sized
成为 Trait
的超特征就是您选择退出对象安全的方式,这使得构建 dyn Trait
.
相反,解决这个问题的方法是使用类似指针的类型:
Box<dyn Trait>
创建一个拥有的指针&dyn Trait
创建参考Arc<dyn Trait>
创建一个引用计数指针指针类型的选择取决于您的用例,但在大多数情况下,Box<dyn Trait>
很好,并且是一个很好的起点。