文章目录

  • Rust 函数
    • 函数
    • 函数(方法)讲解
      • 1.什么是函数(方法)
      • 2.方法(函数的构成)
        • 1. 什么是形参
        • 2.什么是实参
        • 3.定义方法(函数)类型
          • (方法)函数类型
        • 5.方法(函数)的 return
          • 使用 `return` 关键字
          • 隐式返回
        • 5.关联方法,自由函数
          • 关联方法(Associated Methods)
          • 自由函数(Free Functions)
    • 技术细节
      • 带有返回值的方法
      • 不带返回值的方法

Rust 函数

函数

在大部分语言中函数或者叫方法,函数(方法)在大多数语言中是不可缺少的,因此到处可见,所以函数(方法)是什么呢?
在 Rust 中,函数被也可以称为方法(methods),它们是 Rust 程序中的基本构建块之一。方法是一段被命名并可重复调用的代码块,用于执行特定的任务。方法可以接受参数并返回值,它们通常用于执行特定的操作或完成特定的计算。

你说得对,让我更具体一些。在 Rust 中,函数和方法有一些区别:

  1. 函数(Functions):在 Rust 中,函数是一段独立的代码块,可以接受参数并返回值,但它们不附属于任何特定的类型。函数可以在任何地方被调用,它们通常用于执行一些独立的操作,而不依赖于特定的数据结构或类型。

  2. 方法(Methods):方法是与特定类型相关联的函数。它们通过"self"参数(或"&self"、"&mut self"等)来访问其所属的类型的数据。在 Rust 中,方法的调用通常使用"对象.方法名()"的语法,其中对象是方法所属的类型的实例。方法的定义通常在特定类型的实现块(impl block)中。

在 Rust 中,尤其是在处理结构体或枚举类型时,很多代码确实会写在方法里面,这样可以更好地组织和管理代码,并使代码更具有结构性和可读性。

达标的 Rust 方法应该满足以下要求:

  1. 与类型相关联:方法应该与特定类型相关联,并通过"self"参数来访问该类型的数据。

  2. 遵循所有函数的要求:方法也必须遵循函数的所有要求,包括安全性、性能、可读性和健壮性。

  3. 符合面向对象的原则:方法的设计应该符合面向对象编程的原则,即将操作和数据封装在一起,提供一种清晰的接口供用户使用。

下面是一个简单的 Rust 方法的结构组成,包括可选的修饰符:

// 可选的修饰符:pub 等
fn 方法名(&self, 参数1: 参数类型, 参数2: 参数类型, ...) -> 返回类型 {
    // 执行语句
    ...
    // 可选的返回值
    return 返回值;
}

让我们来解释一下每个部分:

  1. fn: 这个关键字用于声明一个函数。

  2. 方法名: 函数的名称,你可以根据需要为函数起一个合适的名字。

  3. (&self): 这个是函数的第一个参数,表示方法是一个对象的方法。self 表示当前对象的引用,& 表示这是一个不可变引用,如果需要修改对象,可以使用 &mut self

  4. 参数1: 参数类型, 参数2: 参数类型, ...: 这是函数的参数列表,每个参数都有一个名称和一个类型。

  5. -> 返回类型: 这是函数的返回类型,表示函数执行完毕后将返回的值的类型。

  6. {}: 函数体由一对大括号包围,里面包含了函数的具体实现。

  7. // 执行语句: 这是函数内部的执行语句,你可以在这里编写任何你想要执行的代码逻辑。

  8. return 返回值;: 这是一个可选项,用于指定函数的返回值。你可以使用 return 关键字来显式地返回一个值,也可以省略返回值,这样函数将会返回一个空的元组 ()

可选的修饰符 pub 可以用于标记函数或其他项为公共的,这样它们就可以被外部模块访问。

函数(方法)讲解

1.什么是函数(方法)

简单理解方法(函数)可以理解为一个载体,好比我是一名优秀的博客作家【方法,函数】,博客作家只是我的代号【方法名,函数名】,并不能代表我的能编写很好的文章,因此就需要我们在方法(函数中进行完善一些行为)这些行为定义了我写博客的过程,这个过程就是我要编写代码的处理行为亦或是我的内在【方法内部的代码】

2.方法(函数的构成)

  1. fn: 这个关键字用于声明一个函数。

  2. 方法名: 函数的名称,你可以根据需要为函数起一个合适的名字。

  3. (&self): 这个是函数的第一个参数,表示方法是一个对象的方法。self 表示当前对象的引用,& 表示这是一个不可变引用,如果需要修改对象,可以使用 &mut self

  4. 参数1: 参数类型, 参数2: 参数类型, ...: 这是函数的参数列表,每个参数都有一个名称和一个类型。

  5. -> 返回类型: 这是函数的返回类型,表示函数执行完毕后将返回的值的类型。

  6. {}: 函数体由一对大括号包围,里面包含了函数的具体实现。

  7. // 执行语句: 这是函数内部的执行语句,你可以在这里编写任何你想要执行的代码逻辑。

  8. return 返回值;: 这是一个可选项,用于指定函数的返回值。你可以使用 return 关键字来显式地返回一个值,也可以省略返回值,这样函数将会返回一个空的元组 ()

1. 什么是形参

在 Rust 中,方法的形参(formal parameters)指的是方法定义中声明的参数,用于接收调用该方法时传入的值。形参位于方法签名的括号内,在括号内以逗号分隔,每个形参都由参数名和参数类型组成。

下面是一个简单的示例,展示了一个具有两个形参的方法的定义:

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 方法定义,这里的`&self`是一个形参,表示该方法可以通过引用调用,并且该引用是不可变的
    // 方法的第二个形参`increase_by`是一个u32类型的参数,用于指定增加的值
    fn increase_size(&mut self, increase_by: u32) {
        self.width += increase_by;
        self.height += increase_by;
    }
}

fn main() {
    let mut rect = Rectangle {
        width: 10,
        height: 20,
    };

    println!("Before increase: width = {}, height = {}", rect.width, rect.height);

    // 调用`increase_size`方法,并传入一个值作为`increase_by`形参
    rect.increase_size(5);

    println!("After increase: width = {}, height = {}", rect.width, rect.height);
}

在上面的示例中,increase_size方法有两个形参:&mut selfincrease_by。其中,&mut self 表示方法的接收者是一个可变引用,并且这是一个隐式参数,它不需要在调用方法时显式传入。而 increase_by 则是方法的第二个形参,它是一个 u32 类型的参数,用于指定增加的值。

形参在方法的定义中起到了接收外部传入值的作用,允许方法在执行时操作这些值,并根据需要进行计算或处理。

2.什么是实参

在 Rust 中,实参(actual parameters)是指在调用函数或方法时传递给它们的具体值或表达式。实参是实际被传递给函数或方法的数据,在调用过程中用于填充函数或方法的形参。

以下是一个简单示例,演示了如何在 Rust 中使用实参来调用函数和方法:

// 定义一个函数,接受两个参数,并打印它们的和
fn add_numbers(a: i32, b: i32) {
    println!("The sum of {} and {} is: {}", a, b, a + b);
}

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 方法定义,接受一个额外的参数,并将该参数添加到宽度和高度上
    fn increase_size(&mut self, increase_by: u32) {
        self.width += increase_by;
        self.height += increase_by;
    }
}

fn main() {
    // 调用函数`add_numbers`,并传入两个实参:3 和 5
    add_numbers(3, 5);

    let mut rect = Rectangle {
        width: 10,
        height: 20,
    };

    println!("Before increase: width = {}, height = {}", rect.width, rect.height);

    // 调用`increase_size`方法,并传入一个实参作为`increase_by`参数
    rect.increase_size(5);

    println!("After increase: width = {}, height = {}", rect.width, rect.height);
}

在上面的示例中,add_numbers函数被调用时,传递了两个实参:3 和 5。这两个实参填充了函数定义中的形参 ab。同样地,在调用 increase_size 方法时,传递了一个实参 5,它填充了方法定义中的 increase_by 形参。

实参提供了函数和方法执行所需的具体数据,允许程序根据需要操作或处理这些数据。

3.定义方法(函数)类型

在 Rust 中,方法和函数都可以被视为类型,这些类型主要与它们的签名(signature)相关。方法类型(Method Type)和函数类型(Function Type)可以被用作变量的类型、函数的参数类型或返回类型等。

(方法)函数类型

函数类型表示一个函数的签名,它是用来定义方法(函数)所要返回的是什么类型。在 Rust 中,函数类型可以使用 fn 关键字定义。例如,具有参数类型为 i32i32,返回类型为 i32 的函数类型可以写成 fn(i32, i32) -> i32

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    let func: fn(i32, i32) -> i32 = add;
    println!("Result: {}", func(3, 5));
}

在上面的示例中,add 函数的类型是 fn(i32, i32) -> i32,并且可以将其赋值给变量 func,因为它们的类型匹配。

5.方法(函数)的 return

在 Rust 中,方法(以及函数)可以使用 return 关键字来提前返回值,也可以通过简单地将要返回的表达式放在函数体的最后来隐式返回值。

使用 return 关键字

在 Rust 中,你可以使用 return 关键字来显式地提前返回值。这在你想要在函数的中间部分返回结果,并且不希望继续执行函数的余下部分时很有用。

fn is_even(num: i32) -> bool {
    if num % 2 == 0 {
        return true;
    }
    false // 这一行也可以省略,因为最后一个表达式会被隐式返回
}

fn main() {
    println!("Is 5 even? {}", is_even(5)); // 输出:Is 5 even? false
}

在上面的示例中,如果 num 是偶数,is_even 函数会提前返回 true,否则会返回 falsereturn 关键字可以在任何地方使用,即使在代码块中。

隐式返回

在 Rust 中,函数和方法的最后一个表达式会被隐式地作为返回值。这意味着你不需要使用 return 关键字来返回值,只需要将要返回的值放在函数体的最后即可。

fn is_even(num: i32) -> bool {
    num % 2 == 0 // 这是最后一个表达式,会被隐式返回
}

fn main() {
    println!("Is 5 even? {}", is_even(5)); // 输出:Is 5 even? false
}

在上面的示例中,is_even 函数的最后一个表达式是 num % 2 == 0,因此它会被隐式地作为返回值。

无论是使用 return 关键字还是隐式返回,都可以有效地返回值,但根据个人偏好和代码清晰度,你可以选择其中之一。通常来说,如果函数或方法比较简单,且只有一个返回点,那么使用隐式返回可能更清晰。

5.关联方法,自由函数

在 Rust 中,方法(Methods)可以分为两种类型:关联方法(Associated Methods)和自由函数(Free Functions)。其中,关联方法是绑定到结构体、枚举或 trait 的方法,而自由函数则是没有绑定到特定类型的函数。

关联方法(Associated Methods)

关联方法是绑定到类型上的方法,它们使用 impl 块在类型的上下文中定义。关联方法没有类型限制,因为它们直接与类型相关联。

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 这是一个关联方法
    fn new(width: u32, height: u32) -> Rectangle {
        Rectangle { width, height }
    }
}

fn main() {
    let rect = Rectangle::new(10, 20); // 调用关联方法
}

在上面的例子中,new 是一个关联方法,因为它使用 impl 块与 Rectangle 类型相关联。这个方法不接受任何类型的参数,因为它不需要一个特定的实例来调用。

自由函数(Free Functions)

自由函数是不绑定到类型的函数。它们不在 impl 块中定义,而是直接在模块中定义。

// 这是一个自由函数
fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn main() {
    let result = add(3, 5); // 调用自由函数
    println!("Result: {}", result);
}

在这个例子中,add 是一个自由函数,因为它不与任何特定的类型相关联。

总的来说,在 Rust 中,无论是关联方法还是自由函数,它们都是类型无关的。不像一些其他语言,如面向对象语言中的方法,它们必须与特定的类或对象相关联。

技术细节

在 Rust 中,方法和函数都是严格的类型安全的,并且方法始终与其接收者的类型相关联。

另外,Rust 中的函数和方法都可以有返回值。即使函数或方法不返回任何值,它们也会隐式返回 (),即 unit 类型,表示一个空的元组。这种情况下,你可以说函数或方法的返回值为空。

下面分别展示 Rust 中带有返回值的方法和不带返回值的方法的示例:

带有返回值的方法

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 这是一个带有返回值的方法
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect = Rectangle { width: 10, height: 20 };
    let area = rect.area(); // 调用带有返回值的方法
    println!("Area: {}", area); // 输出:Area: 200
}

在上面的示例中,area 是一个带有返回值的方法,它返回 u32 类型的矩形的面积。

不带返回值的方法

struct Counter {
    count: u32,
}

impl Counter {
    // 这是一个不带返回值的方法
    fn increment(&mut self) {
        self.count += 1;
    }
}

fn main() {
    let mut counter = Counter { count: 0 };
    counter.increment(); // 调用不带返回值的方法
    println!("Count: {}", counter.count); // 输出:Count: 1
}

在这个示例中,increment 是一个不带返回值的方法。它对 Counter 结构体的 count 字段进行增量操作,但不返回任何值。

总之,Rust 中的方法和函数都可以有返回值,即使函数或方法不返回任何值,它们也会隐式返回 ()

04-17 09:53