我再次与一辈子战斗。或实际上,我有点打赢了比赛,但我不确定结果是否是处理该问题的预期方式。
假设我有一个具有两个生命周期的结构: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 () {
}
围栏:http : //is.gd/A3ol4w
就使用寿命而言,这可以简化吗?特别是,我想知道该特性是否真的需要定义所有这些生存期,或者是否有办法仅在结构上定义它们?
如果无法忽略trait的生存期,是否意味着最好的做法是指定trait上所有可能的生存期,以使实现者具有最大的灵活性?我的意思是,如果该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 () {
}
游戏围栏:http://is.gd/NzigjX
这就是为什么我要问自己,作为特征作者,我是否应该假设所有引用的方法最终都可能被特征实现者存储在字段中,因此我需要在特征上指定所有生存期,以使其成为可能对于实施者。
没有一种万能的解决方案。作为特质作者,您必须考虑自己想做什么和想要实现什么。
如果要具有将值的生存期与结构的生存期参数相关联的功能,则必须将生存期放在特征上。这通常这样做是因为你的特质有预期与寿命相同的值运行多个方法。这可能类似于getter / setter对。在我编写的一些代码中,我传递了&str
我保留了一段时间的引用,然后才“完成”它们。如果出于任何原因需要存储引用,则必须在特征上具有生命周期。
在您的情况下,您有一个构造函数方法,如果该结构确实需要,则需要知道生存期。如果该功能确实与众不同,则可以将该功能与其余特征分开。在您的示例中,该work_with_inner
方法不接受self
参数,因此非常不同。如果您使用过self
但不需要与from的生命周期进行交互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 () {}
您会看到我还应用了一件可以减少生命周期的事情。如果您的结构只是引用(或引用和其他小Copy
类型),则无需将引用传递给该结构。引用是可复制的,并且跟踪包含结构的生存期没有用。
社论-我不认为“构造函数”方法通常在特征中有用。您通常希望提供不同的集合或参数,这就是为什么首先要使用不同类型的原因。也许您的真实代码在特征中使用的不是构造函数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句