如何实现引用值和拥有值的特征?

问题描述 投票:0回答:1

我定义了以下特征:

trait Read<T> {
    fn next_row<'c>(&'c mut self) -> Result<std::option::Option<T>>;
}

(显然

'c
会被省略,但我只是想以后能够参考它)

我已经为结构体

ReaderA
实现了这个,以返回拥有的值:

struct ReaderA {
    data: Vec<Vec<u8>>
}

impl Read<Vec<u8>> for ReaderA {
    fn next_row<'c>(&'c mut self) -> Result<std::option::Option<Vec<u8>>> {
        Ok(self.data.pop())
    }
}

毫不奇怪,这非常有效。当我尝试为某些结构实现此方法以返回借用的值时,就会出现问题:

ReaderB

这行不通。签名与定义不匹配,因为该特征不希望 
struct ReaderB { data: Vec<Vec<u8>> } impl Read<&Vec<u8>> for ReaderB { fn next_row<'c>(&'c mut self) -> Result<std::option::Option<&'c Vec<u8>>> { Ok(self.data.first()) } }

包含在返回值中。我做错了什么?

我可以将生命周期添加为特征通用参数,但这感觉没有必要:我不想指定其他生命周期,我只是希望它共享 

'c

借用的生命周期(我认为)。我也宁愿不必在每个特征的实现中包含生命周期,并在每个结构中包含

&mut self
,即使它们不返回借用的值。我也不想遇到像
this
这样的事情,但我真的不明白我在做什么。 我觉得这可能与 HRTB 有关,但我不知道如何让它发挥作用。

我有点迷失了一生,所以请在你的答案中包含尽可能多的细节。

rust lifetime
1个回答
0
投票

不鼓励使用泛型作为返回值,除非您正在实现一个转换函数或类似的函数,您的特征的用户想要决定它应该是什么类型。如果每个实现类型只有一个返回类型,请改用
    关联类型
  • ,例如PhantomData
    特征定义没有捕获
  • std::iter::Iterator
  • 是否应该引用
    T
    。在一种情况下确实如此,在另一种情况下则不然。这是你的方法失败的主要问题;如果有人想使用该特征,他可以保留生成的值,但销毁
    Self
    对象,这应该说明为什么示例代码中的
    Read
    实现被正确禁止。
    
    
  • 如果将泛型转换为关联类型并在特征中进行注释,那么
ReaderB

应始终比返回值更长寿,那么它就可以工作:

Self

	
© www.soinside.com 2019 - 2024. All rights reserved.