我再次与生命斗争.或者实际上,我有点赢了这场比赛,但我不确定结果是否是预定的处理方式.
假设我有两个生命周期的结构:Inner<'a, 'b>.现在我想写一个定义new(inner: &Inner) -> Self方法的特征.实现者应该可以自由地将引用存储在Inner内部并定义其他方法来处理它.
我想出了这个(它有效!)但我有几个问题
struct Inner<'a, 'b>{
foo: &'a str,
bar: &'b str
}
trait Worker<'data, 'a, 'b> {
fn new (inner: &'data Inner<'a, 'b>) -> Self;
fn work_with_inner () { println!("works on inner");}
}
struct SomeWorker<'inner, 'a:'inner, 'b:'inner> {
inner: &'inner Inner<'a, 'b>
}
impl<'data, 'a, 'b> Worker<'data, 'a, 'b> for SomeWorker<'data, 'a, 'b> {
fn new (inner: &'data Inner<'a, 'b>) -> Self {
SomeWorker {
inner: inner
}
}
}
fn main () {
}
Run Code Online (Sandbox Code Playgroud)
就生命周期而言,这可以简化吗?特别是,我想知道这个特性是否真的需要定义所有这些生命周期,或者是否有办法只在结构上定义它们?
如果没有办法省略特征的生命周期那么这意味着最好的做法是在特征上指定所有可能的生命周期,以便为实施者提供最大的灵活性?我的意思是,如果SomeWorker结构不想存储引用Inner,整个事物,包括特征,可能会简单得多.
看,没有生命.
struct Inner<'a, 'b>{
foo: &'a str,
bar: &'b str
}
trait Worker {
fn new (inner: &Inner) -> Self;
fn work_with_inner () { println!("works on inner");}
}
struct SomeWorker;
impl Worker for SomeWorker {
fn new (inner: &Inner) -> Self {
SomeWorker
}
}
fn main () {
}
Run Code Online (Sandbox Code Playgroud)
这就是为什么我问自己作为一个特质作者,我应该假设所有引用参考的方法最终都可能被特征实现者存储在一个字段中,因此我需要在特征上指定所有生命周期以使其成为可能对于实现者.
没有一个通用的解决方案.作为特质作者,您必须考虑您尝试做什么以及您想要实现的目标.
如果您希望能够将值生存期与结构的生命周期参数相关联,则必须将生命周期放在特征上.这通常这样做是因为你的特质有预期与寿命相同的值运行多个方法.这可能类似于getter/setter对.在我写的一些代码中,我正在传递&str我在"敲定"它们之前保留一段时间的引用.如果您因任何原因需要存储引用,那么您将需要具有该特征的生命周期.
在您的情况下,您有一个构造函数方法,需要知道结构的生命周期.如果它真的与众不同,你可以将该功能与其他特征分开.在您的示例中,该work_with_inner方法不接受self参数,因此这将是非常不同的.如果您使用self但不需要与生命周期进行交互Inner,它仍然可以帮助:
trait WorkerBuilder<'a, 'b> {
fn new(inner: Inner<'a, 'b>) -> Self;
}
trait Worker {
fn do_work(&self);
}
#[derive(Debug)]
struct Inner<'a, 'b>{
foo: &'a str,
bar: &'b str,
}
// This does track `Inner`
#[derive(Debug)]
struct SomeWorker<'a, 'b>(Inner<'a, 'b>);
impl<'a, 'b> WorkerBuilder<'a, 'b> for SomeWorker<'a, 'b> {
fn new(inner: Inner<'a, 'b>) -> SomeWorker<'a, 'b> {
SomeWorker(inner)
}
}
impl<'a, 'b> Worker for SomeWorker<'a, 'b> {
fn do_work(&self) { println!("Doing work, {:?}", self.0) }
}
// This doesn't track `Inner`
#[derive(Debug)]
struct DumbWorker;
impl<'a, 'b> WorkerBuilder<'a, 'b> for DumbWorker {
fn new(inner: Inner<'a, 'b>) -> DumbWorker {
DumbWorker
}
}
fn main () {}
Run Code Online (Sandbox Code Playgroud)
您会看到我还应用了一件可以减少生命周期的事情.如果您的结构只是引用(或引用和其他小Copy类型),则无需传递对该结构的引用.引用是可复制的,跟踪包含结构的生命周期是没有用的.
编辑 - 我不觉得"构造函数"方法通常在特征中有用.您经常需要提供不同的设置或参数,这就是您首先使用不同类型的原因.也许你的真实代码在特性中使用的不是构造函数.