面试题答案
一键面试trait Printable {
fn print(&self);
}
struct Inner<'a, T> where T: 'a {
value: &'a T
}
struct Outer<'a, T> where T: 'a + Printable {
inner: Inner<'a, T>
}
impl<'a, T> Printable for Outer<'a, T> where T: 'a + Printable {
fn print(&self) {
self.inner.value.print();
}
}
fn main() {
struct CustomType;
impl Printable for CustomType {
fn print(&self) {
println!("CustomType");
}
}
let custom = CustomType;
let outer = Outer { inner: Inner { value: &custom } };
outer.print();
}
生命周期、泛型和trait之间的相互作用及约束关系
- 生命周期:
Inner
结构体中的value
字段是一个引用,具有生命周期'a
。这意味着Inner
实例的生命周期依赖于它所引用的值的生命周期。Outer
结构体中的inner
字段是Inner
类型,所以Outer
结构体的生命周期也受限于Inner
中引用的生命周期'a
。- 在
main
函数中,custom
是一个局部变量,当创建Outer
实例时,Inner
中的value
引用custom
,因此Outer
实例的生命周期不能超过custom
的生命周期。这里通过生命周期标注,确保了引用的有效性,避免悬垂引用。
- 泛型:
Inner
和Outer
结构体都使用了泛型T
。泛型T
允许这些结构体在不指定具体类型的情况下进行定义,提高了代码的复用性。Inner
结构体对泛型T
只有生命周期约束T: 'a
,表示T
的生命周期至少和'a
一样长。Outer
结构体对泛型T
有更严格的约束,不仅要求T: 'a
,还要求T: Printable
,即T
类型必须实现Printable
trait。
- trait:
Printable
是一个 trait,定义了print
方法。任何实现了Printable
trait 的类型都必须实现print
方法。CustomType
实现了Printable
trait,从而满足了Outer
结构体对泛型T
的Printable
约束。Outer
结构体也实现了Printable
trait,在其print
方法实现中,调用了Inner
中引用值的print
方法,这依赖于T
实现了Printable
trait。
通过生命周期、泛型和trait的协同工作,这段代码实现了灵活且类型安全的抽象,允许不同类型在满足特定约束的情况下复用相同的代码结构。