我正在学习Rust中的命名生命周期,而且我很难理解它们在实现特征时所代表的含义。具体来说,我无法理解来自libserialize/hex.rs的这段代码。为简洁起见,我删除了一些评论。
pub trait ToHex {
fn to_hex(&self) -> ~str;
}
static CHARS: &'static[u8] = bytes!("0123456789abcdef");
impl<'a> ToHex for &'a [u8] {
fn to_hex(&self) -> ~str {
let mut v = slice::with_capacity(self.len() * 2);
for &byte in self.iter() {
v.push(CHARS[(byte >> 4) as uint]);
v.push(CHARS[(byte & 0xf) as uint]);
}
unsafe {
str::raw::from_utf8_owned(v)
}
}
}
我理解CHARS定义中的'static
生命周期,但我对ToHex实现中定义的生命周期感到困惑。 命名生命周期在特征的实现中代表什么?
答案 0 :(得分:8)
在那个特殊情况下 - 并不多。 &[u8]
不是完全指定的类型,因为缺少生命周期,并且实现必须是完全指定的类型。因此,实现是通过任意(对于通用参数是无约束的)生存期'a
进行参数化的。
在这种情况下,您不能再次使用它。但是,在某些情况下,您希望约束函数参数或将值返回到相同的生命周期。
然后你可以这样写:
impl<'a, T> ImmutableVector<'a, T> for &'a [T] {
fn head(&self) -> Option<&'a T> {
if self.len() == 0 { None } else { Some(&self[0]) }
}
…
}
这意味着返回值的生命周期与self
,'a
相同。
顺便说一句,为了搞清楚,可以在每个函数上手动编写 的生命周期
impl<'a, T> ImmutableVector<'a, T> for &'a [T] {
fn head<'a>(&'a self) -> Option<&'a T> {
if self.len() == 0 { None } else { Some(&self[0]) }
}
…
}
...这表明必须指定要实现的类型的生命周期才能确保完全指定类型。它允许你为使用该生命周期内的所有函数写一点点。