我无法理解 Rust 中的特征和对象安全性。
我有一个StoreTrait
用于存储一些数据的Resource
结构和一个包含对 a 的引用的结构StoreTrait
。
我希望Resource
有对实例的引用store
,因为Resource
将使用的许多方法store
,并且我不想显式传递store
给 上的每个方法Resource
。
我还需要将逻辑驻留在特征中,因为我有各种需要共享它的实现(内存中和磁盘存储)。所以把它移到 impl 中并不是我想要的。
在Store
trait 中,我尝试传递&Self
给一个函数,但它失败了,因为&Self
is not Sized
:
pub trait StoreTrait {
fn create_resource(&self) {
let agent = Resource::new(self);
}
}
struct Resource<'a> {
store: &'a dyn StoreTrait,
}
impl<'a> Resource<'a> {
pub fn new(store: &dyn StoreTrait) -> Resource {
Resource { store }
}
}
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> src/lib.rs:3:35
|
3 | let agent = Resource::new(self);
| ^^^^ doesn't have a size known at compile-time
|
= note: required for the cast to the object type `dyn StoreTrait`
help: consider further restricting `Self`
|
2 | fn create_resource(&self) where Self: Sized {
| ^^^^^^^^^^^^^^^^^
这可能会成为 XY 问题
编译器建议where Self: Sized
在这些方法中使用边界。但是,这在稍后save_resource()
从 a调用时会导致另一个问题Resource
,因为这意味着我正在调用带有Sized
边界的 trait 对象上的方法。
pub trait StoreTrait {
// So after adding the trait bounds here...
fn create_resource(&self)
where
Self: Sized,
{
let agent = Resource::new(self);
}
// And here (internal logic requires that)...
fn save_resource(&self, resource: Resource)
where
Self: Sized,
{
// This now requires `Self: Sized`, too!
self.create_resource()
}
}
pub struct Resource<'a> {
pub store: &'a dyn StoreTrait,
}
impl<'a> Resource<'a> {
pub fn new(store: &dyn StoreTrait) -> Resource {
Resource { store }
}
pub fn save(&self) {
self.store.save_resource(self)
}
}
error: the `save_resource` method cannot be invoked on a trait object
--> src/lib.rs:26:20
|
13 | Self: Sized;
| ----- this has a `Sized` requirement
...
26 | self.store.save_resource(self)
| ^^^^^^^^^^^^^
如何规避设置特征界限?或者如何防止在 trait 对象上调用方法?也许我正在做其他没有意义的事情?
编辑:我最终改变了函数的参数。每当我使用&dyn StoreTrait
时,我都会切换到&impl StoreTrait
. 这意味着每个实现都会编译具有该签名的函数,这使得二进制文件更大一些,但它现在sized
可以满足要求。耶!