返回文章列表

文章

Rust中::和.方法调用的区别

• .: 用于调用实例上的方法 (self, &self, &mut self)。 • ::: 用于调用类型上的关联函数(没有 self)或访问模块/枚举/常量。

在 Rust 中,::. 都用于访问与类型相关的项,但它们用于访问不同类型的项:

  1. .** (点运算符): 用于调用实例方法** (Instance Methods)。
    • 场景: 当你有一个特定类型(如 structenum)的实例(一个具体的变量值)时,你想调用定义在该类型上的、操作这个实例的函数。
    • 特点: 实例方法通常在 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)或访问模块/枚举/常量。 理解这个区别对于区分操作是针对一个具体的数据值,还是针对数据类型本身或其组织结构至关重要。