文章
Rust中::和.方法调用的区别
• .: 用于调用实例上的方法 (self, &self, &mut self)。 • ::: 用于调用类型上的关联函数(没有 self)或访问模块/枚举/常量。
在 Rust 中,:: 和 . 都用于访问与类型相关的项,但它们用于访问不同类型的项:
.** (点运算符): 用于调用实例方法** (Instance Methods)。- 场景: 当你有一个特定类型(如
struct或enum)的实例(一个具体的变量值)时,你想调用定义在该类型上的、操作这个实例的函数。 - 特点: 实例方法通常在
impl块中定义,并且它们接收self(表示拥有权)、&self(表示共享借用) 或&mut self(表示可变借用) 作为第一个参数。 - 语法:
instance.method_name(arguments) - 例子:
- 场景: 当你有一个特定类型(如
struct Rectangle { width: u32, height: u32, }
impl Rectangle { // 这是一个实例方法,接收一个不可变引用 &self fn area(&self) -> u32 { self.width * self.height // 通过 self 访问实例的字段 }
// 这是一个实例方法,接收可变引用 &mut self
fn set_width(&mut self, new_width: u32) {
self.width = new_width; // 通过 self 修改实例的字段
}
// 这是一个实例方法,接收 self (拥有权)
// 调用后,rect 变量将失效
fn consume(self) {
println!("Consumed a rectangle with area: {}", self.width * self.height);
}
}
fn main() { let mut rect = Rectangle { width: 10, height: 5 };
// 使用 . 调用实例方法 area()
// rect 是一个 Rectangle 的实例
println!("Area: {}", rect.area()); // 输出: Area: 50
// 使用 . 调用实例方法 set_width()
rect.set_width(12); // 修改 rect 实例
// 使用 . 调用实例方法 consume()
// print_size(rect); // 这行将因为所有权转移而报错,如果 consume() 不在此处调用
// rect.consume(); // 调用后 rect 不再有效
}
- **总结**: 当你有一个具体的值,想调用该值所属类型上定义的操作该值的函数时,使用 `.`。 2. **`::`**** (双冒号运算符)**: 用于访问**关联函数** (Associated Functions) 或**模块/枚举/常量**中的项。 - **场景 1 (关联函数)**: 调用定义在类型上,但**不**需要一个具体实例来调用的函数。这些函数通常用作构造函数、工厂方法或与类型相关的通用工具函数。它们不接收 `self` 作为第一个参数(尽管它们可以接受该类型的实例作为其他参数)。 - **场景 2 (模块/枚举/常量)**: 访问定义在模块、枚举内部的变体,或者与类型/trait 关联的常量。 - **特点**: 关联函数直接属于类型本身,而不是某个实例。 - **语法**: `Type::associated_function_name(arguments)` 或 `Type::ASSOCIATED_CONSTANT_NAME` 或 `ModuleName::item` 或 `EnumName::Variant`. - **例子**: rust
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle { // 这是一个关联函数(常常用作构造函数) // 它不接收 self fn new(width: u32, height: u32) -> Rectangle { Rectangle { width, height } }
// 这是一个关联函数(例如,一个工厂方法)
// 它也不接收 self
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
// 这是一个实例方法 (这里重复是为了对比)
fn area(&self) -> u32 {
self.width * self.height
}
}
enum Status { Active, Inactive, }
trait Shape { const DEFAULT_SIZE: u32 = 10; // 关联常量 fn get_area(&self) -> u32; // 实例方法 }
impl Shape for Rectangle { fn get_area(&self) -> u32 { self.area() // 可以调用 Rectangle 的实例方法 } }
fn main() { // 使用 :: 调用关联函数 new() // Rectangle 是类型本身 let rect1 = Rectangle::new(20, 10);
// 使用 :: 调用关联函数 square()
let sq1 = Rectangle::square(8);
// 关联函数常常用于实现 String::from(), Vec::new(), HashMap::new() 等
let s = String::from("hello"); // String 的关联函数 from()
let v: Vec<i32> = Vec::new(); // Vec 的关联函数 new()
// 使用 :: 访问枚举变体
let status1 = Status::Active;
let status2 = Status::Inactive;
// 使用 :: 访问关联常量 (与 trait 关联的常量)
println!("Default shape size: {}", <Rectangle as Shape>::DEFAULT_SIZE); // 需要完整的路径如果 trait 常量与类型同名
// 或者如果只与类型关联的常量: Type::MY_CONST
// 使用 . 调用实例方法 (与 Shape trait 关联的实例方法)
println!("Rectangle shape area: {}", rect1.get_area());
}
```
- 总结: 当你需要调用属于类型本身(而不是某个具体值)的函数,或者需要访问属于类型/模块/枚举的常量或变体时,使用 ::。
简要总结:
.: 用于调用实例上的方法 (self,&self,&mut self)。::: 用于调用类型上的关联函数(没有self)或访问模块/枚举/常量。 理解这个区别对于区分操作是针对一个具体的数据值,还是针对数据类型本身或其组织结构至关重要。