面试题答案
一键面试Trait定义
trait IterableProcessor<T> {
fn process_iterable(&self, iterable: &[T]);
}
实现示例
struct MyProcessor;
impl IterableProcessor<&str> for MyProcessor {
fn process_iterable(&self, iterable: &[&str]) {
for item in iterable {
println!("Processing: {}", item);
}
}
}
生命周期省略规则在泛型和trait场景下的微妙之处
- 输入生命周期省略:在方法签名中,当只有一个输入借用参数时,Rust会自动为其添加一个生命周期参数。例如,
fn process_iterable(&self, iterable: &[T])
中,&self
和&[T]
都省略了生命周期参数,但实际上它们都有隐式的生命周期参数,并且在这种情况下,它们的生命周期是相同的(因为只有一个输入借用)。 - 输出生命周期省略:如果方法返回一个借用值,且返回值的生命周期与某个输入参数的生命周期相关,Rust可以省略返回值的生命周期参数。但如果返回值的生命周期与任何输入参数的生命周期都不相关,则必须显式声明生命周期参数。在我们的trait定义中,由于没有返回借用值,所以这一点不涉及。
潜在的陷阱
- 多个输入借用:当方法有多个输入借用参数时,生命周期省略规则不再适用,必须显式声明生命周期参数。例如,如果我们要在
process_iterable
方法中同时接受两个不同的借用参数,就需要显式声明生命周期,如下:
trait IterableProcessor<T> {
fn process_iterable<'a, 'b>(&'a self, iterable1: &'a [T], iterable2: &'b [T]);
}
- 返回借用值:如前所述,如果方法返回一个借用值,且其生命周期与输入参数无关,必须显式声明生命周期。否则,编译器会报错,因为无法推断出正确的生命周期关系。例如:
trait IterableProcessor<T> {
fn get_first(&self, iterable: &[T]) -> &T; // 错误,需要显式声明生命周期
}
正确的做法是:
trait IterableProcessor<T> {
fn get_first<'a>(&'a self, iterable: &'a [T]) -> &'a T;
}