Rust 的 impl 语法详解
impl(implementation)是 Rust 中用于为类型定义方法 和实现 trait 的关键字。它有两种主要形式:固有实现(inherent impl) 和 trait 实现(trait impl)。下面逐一介绍。
1. 固有实现(Inherent Impl)
为某个具体类型直接添加方法和关联函数,不涉及任何 trait。
rust
struct Point {
x: f64,
y: f64,
}
impl Point {
// 关联函数(没有 self,类似其他语言的静态方法)
fn new(x: f64, y: f64) -> Self {
Point { x, y }
}
// 方法(有 self 参数)
fn distance_to(&self, other: &Point) -> f64 {
((self.x - other.x).powi(2) + (self.y - other.y).powi(2)).sqrt()
}
// 可变方法
fn translate(&mut self, dx: f64, dy: f64) {
self.x += dx;
self.y += dy;
}
// 消费 self 的方法
fn into_tuple(self) -> (f64, f64) {
(self.x, self.y)
}
}
要点:
- 一个类型可以有多个
impl块(编译器会合并)。 self有三种接收形式:self(按值)、&self(不可变借用)、&mut self(可变借用)。- 关联函数(无
self)通过Type::func()调用;方法通过instance.method()调用。
2. Trait 实现(Trait Impl)
为类型实现某个 trait 所要求的方法。
rust
trait Area {
fn area(&self) -> f64;
// 提供默认实现
fn describe(&self) -> String {
format!("面积是 {:.2}", self.area())
}
}
impl Area for Point {
fn area(&self) -> f64 {
0.0 // 点没有面积,示例而已
}
}
struct Circle { r: f64 }
impl Area for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * self.r * self.r
}
// describe() 使用默认实现
}
孤儿规则(Orphan Rule): 只有当 trait 或类型至少有一个是在当前 crate 中定义 时,才能写 impl Trait for Type。这防止了外部 crate 之间的冲突实现。
3. 泛型 impl 与 trait bound
3.1 泛型类型的方法
rust
struct Wrapper<T> {
value: T,
}
impl<T> Wrapper<T> {
fn new(value: T) -> Self {
Wrapper { value }
}
}
3.2 带约束的 impl(条件实现)
只有当 T 满足某些 trait 时,才提供这些方法:
rust
use std::fmt::Display;
impl<T: Display> Wrapper<T> {
fn show(&self) {
println!("value = {}", self.value);
}
}
3.3 where 子句(约束多时更清晰)
rust
impl<T> Wrapper<T>
where
T: Display + Clone,
{
fn show_cloned(&self) -> String {
format!("{}", self.value.clone())
}
}
impl<T: A + B> 与 impl<T> where T: A + B 完全等价,where 形式在约束复杂时更易读。
4. 泛型 trait 实现
rust
trait MyInto<T> {
fn my_into(self) -> T;
}
impl MyInto<String> for i32 {
fn my_into(self) -> String {
self.to_string()
}
}
5. 关联类型与关联常量
trait 可以带关联类型 和关联常量 ,impl 时一并提供:
rust
trait Container {
type Item; // 关联类型
const CAPACITY: usize = 10; // 关联常量(可带默认值)
fn first(&self) -> Option<&Self::Item>;
}
struct MyVec<T> { data: Vec<T> }
impl<T> Container for MyVec<T> {
type Item = T;
const CAPACITY: usize = 100;
fn first(&self) -> Option<&T> {
self.data.first()
}
}
6. 为 trait 对象 / 引用 / 元组实现
impl 不限于结构体,可为任何本地类型实现:
rust
// 为引用实现
impl Area for &Circle {
fn area(&self) -> f64 { (*self).area() }
}
// 为元组实现(二元组是本地的,所以可以)
impl Area for (f64, f64) {
fn area(&self) -> f64 { self.0 * self.1 }
}
7. Blanket Implementation(全覆盖实现)
为所有满足约束的类型统一实现某个 trait:
rust
trait Printable {
fn print(&self);
}
impl<T: std::fmt::Display> Printable for T {
fn print(&self) {
println!("{}", self);
}
}
现在任何实现了 Display 的类型都自动拥有 print()。标准库的 ToString 就是这样实现的(impl<T: Display> ToString for T)。
8. impl Trait 语法(注意区分)
impl Trait 出现在类型位置 ,与 impl 块是不同概念:
rust
// 参数位置:接受任意实现 Iterator 的类型(语法糖,等价于泛型)
fn sum(it: impl Iterator<Item = i32>) -> i32 {
it.sum()
}
// 返回位置:返回某个实现 Iterator 的匿名类型
fn evens() -> impl Iterator<Item = i32> {
(0..).filter(|x| x % 2 == 0)
}
小结
| 语法形式 | 用途 |
|---|---|
impl Type { ... } |
固有方法/关联函数 |
impl Trait for Type { ... } |
实现 trait |
impl<T> Type<T> { ... } |
泛型类型的实现 |
impl<T: Bound> ... / where |
条件实现 |
impl<T: X> Trait for T |
Blanket 实现 |
type Item = ... / const X |
关联类型 / 关联常量 |
impl Trait(类型位置) |
匿名类型参数/返回值 |
掌握这几种形式,基本就覆盖了 Rust 中 impl 的全部用法。核心原则是:impl 块只是"挂载"方法或 trait 实现的容器,真正的约束由类型参数和 trait bound 决定。