首页 > 解决方案 > 具有特征的寿命和所有权

问题描述

我正在构建一个 Rocket 应用程序,并希望它为我管理一些对象。为此,它们需要是SendSync。这是一个最小的人为示例,显示了我遇到的错误(Playground):

trait MyTrait {
    fn foo(&self) {}
}

struct TraitThing {}

impl MyTrait for TraitThing {
    fn foo(&self) {
        println!("Foo!");
    }
}

struct Thing {
    tt: &'static (dyn MyTrait + Send + Sync),
}

impl Thing {
    fn with_trait(tt: &'static (dyn MyTrait + Send + Sync)) -> Self {
        Self { tt }
    }
}

fn main() {
    let tt = TraitThing {};
    let thing = Thing::with_trait(&tt);
    thing.tt.foo();
}

我可能不明白'static. 理想情况下,我想Thing拥有tt,但据我所知,由于我的 TraitThing 不是Sized(并且可能永远不会是),它不能是一个特征对象,所以它必须通过引用传递。

那么,如何在保留SendandSync特征的同时解决这个问题呢?

谢谢!

附加说明:我在 Rust 书和其他地方阅读了很多关于生命周期和特征的内容,但我希望能进一步阅读材料。

标签: rusttraits

解决方案


您可以使用Box,但它会分配给堆并使用动态调度,这在您的情况下没有用。当您想要实现类似 Trait 的不同类型的列表时,它很有用,例如:

struct Thing {
    tt: Vec<Box<dyn MyTrait + Send + Sync>>,
}

但是在您的情况下,您只有一个元素,因此您可以在此设置中使用泛型:

trait MyTrait {
    fn foo(&self) {}
}

struct TraitThing {}

impl MyTrait for TraitThing {
    fn foo(&self) {
        println!("Foo!");
    }
}

struct Thing<T>
where
    T: MyTrait + Send + Sync
{
    tt: T,
}

impl<T> Thing<T> 
where
    T: MyTrait + Send + Sync
{
    fn with_trait(tt: T) -> Self {
        Self { tt }
    }
}

fn main() {
    let tt = TraitThing {};
    let thing = Thing::with_trait(tt);
    thing.tt.foo();
}

推荐阅读