Rust应用国际化:从零到多语言支持

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:一个小字母,天壤之别

\n\n

你好,未来的 Rust 开发者!如果你已经开始学习 Rust,可能已经注意到编译器是一位严格但公正的老师。它不会容忍拼写错误,更不用说语法混淆了。对于初学者(以及不仅仅是初学者)来说,最常见的陷阱之一就是混淆 self 和 Self。看起来区别只是一个大写字母的大小写而已。但在这个字母背后,隐藏着实例和类型之间的根本区别。

\n\n

在 Stack Overflow 上,这个问题已经收获了数千次浏览,这并非没有原因。今天,我们将一劳永逸地理解 Rust 中 self 和 Self 的区别。我们不会只是阅读枯燥的定义;我们将通过实际示例逐步学习,编写几个小程序。到文章结束时,你不仅会知道它们的区别,还会在直觉上感受到它。我们开始吧!

\n\n

1. self:“我”——指的是实例

\n\n

让我们从 self 开始。在 Rust 中,就像在许多其他语言中一样,self 用于表示结构体或枚举的当前实例。它相当于 C++、Java、JavaScript 或 Python 中的 this。当你编写一个在特定对象上调用的方法时,你会使用 self。

\n\n

在方法签名中,self 有三种主要形式:

\n
    \n
  • self — 获取实例的所有权(消耗实例)。方法调用后,原始对象将不可用。
  • \n
  • &self — 对实例的不可变引用(最常见的情况)。方法可以读取数据但不能更改它。
  • \n
  • &mut self — 对实例的可变引用。方法可以修改结构体的字段。
  • \n
\n\n

让我们写一个简单的示例。假设我们正在创建一个 Student 结构体。

\n\n
struct Student {\n    name: String,\n    year: u32,\n}\n\nimpl Student {\n    // 接受 &self(不可变引用)的方法\n    fn introduce(&self) {\n        println!("Hi! I am {}, studying in year {}.", self.name, self.year);\n    }\n\n    // 接受 &mut self(可变引用)的方法\n    fn advance_to_next_year(&mut self) {\n        self.year += 1;\n        println!("{} is now in year {}!", self.name, self.year);\n    }\n\n    // 接受 self(所有权)的方法\n    fn graduate(self) {\n        println!("{} has graduated in year {}. Goodbye!", self.name, self.year);\n        // self 在这里被销毁,内存被释放\n    }\n}\n\nfn main() {\n    let mut student = Student {\n        name: String::from("Anna"),\n        year: 2,\n    };\n\n    student.introduce(); // &self\n    student.advance_to_next_year(); // &mut self\n    student.graduate(); // self(所有权)\n\n    // 在调用 graduate 之后,变量 'student' 不再可访问!\n    // 取消下面一行的注释,看看编译错误:\n    // student.introduce(); // 错误:移动值的借用\n}
\n\n

注意最后的注释。当我们传递 self(不带引用)时,我们放弃了所有权。这是一个强大的工具,可以精确控制对象的生命周期。在其他语言(例如 Python)中,没有这样的控制——只要存在引用,对象就会一直存活。在 Rust 中,你决定对象何时被“消耗”。

\n\n

2. Self:“我”——指的是类型

\n\n

现在是有趣的部分。Self(大写的 S)是我们正在为其实现方法的类型的类型别名。简单来说,在 impl 块内部,Self 被替换为我们正在处理的结构体或枚举的名称。

\n\n

为什么需要这个?首先,它很方便。你不需要写完整的结构体名称,而是写 Self。其次,它在某些情况下至关重要,例如在 trait 定义中,或者当方法返回当前类型时。

博客

书籍推荐