Rust中的方法
方法其实就是结构体的成员函数,在C语言中的结构体是没有成员函数的,但是Rust毕竟也是一门面向对象的编程语言,所以给结构体加上方法的特性很符合面向对象的特点。
方法的简单概念
方法(method)与函数类似:它们使用 fn
关键字和名称声明,可以拥有参数和返回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它们在结构体的上下文中被定义,并且它们第一个参数总是 self
,它代表调用该方法的结构体实例。
&self
实际上是self: &Self
的缩写,在一个impl
块中,Self
类型是impl
块的类型的别名。方法的第一个参数必须有一个名为self
的Self
类型的参数,所以 Rust 让你在第一个参数位置上只用self
这个名字来缩写。传参的时候可以忽略self的传参。
上面这段话是官方文档对方法的描述。如果学过面向对象的应该理解起来是没人任何问题的,方法就是类中的成员函数,在调用方法是必须通过类的实例对象类调用。
使用方法代替函数的好处:
- 减少self参数的书写
- 组织性好
定义方法
定义方法的方式和定义函数的方式类似,也是采用fn作为标识,但是方法比函数多一点的就是需要被包含在impl中。
impl是implementation的简写,翻译成中文就是实施,实现的意思。在Rust中所有的方法都必须在对应的结构体的impl中实现,并且方法的第一个参数是&self,其中&self就是指向当前对象的引用,类似于C++中的this、Java中的this、Python中的self.
基本结构:
impl 结构体名 { 方法1... 方法2... .... 方法n... } //也可以再开一个impl impl 结构体名 { 方法n+1.... } //其中以上的效果和下面写法等效 impl 结构体名 { 方法1... 方法2... .... 方法n... 方法n+1.... }
可以重开一个impl的特性就像C++中的namespace一样,如果想了解namespace的可自行查询资料。
综上所述,impl的作用就是用来标识哪些方法是属于哪个结构体的。
例子:
struct MM { name: String, age: u8, } impl MM { fn get_name(&self) -> &str { &self.name } fn get_age(&self) -> &u8 { &self.age } } impl MM { fn show(&self) { println!("name: {}", self.name); println!("age: {}", self.age); } } /*上面两个impl等效于以下代码 impl MM { fn get_name(&self) -> &str { &self.name } fn get_age(&self) -> &u8 { &self.age } fn show(&self) { println!("name: {}", self.name); println!("age: {}", self.age); } } */ fn main() { let mm = MM { name: String::from("Alice"), age: 18, }; mm.show(); println!("{}的名字叫: {}, 她今年{}岁了", mm.name, mm.get_name(), mm.get_age()); }
结果:
name: Alice
age: 18
Alice的名字叫: Alice, 她今年18岁了
Rust自动引用和解引用
在C++中访问对象的内容,一般都是使用指针和指针运算符->
来访问对象中的属性(成员变量)和行为(成员函数)。但是在Rust没有和->
等效的运算符。Rust是存在了自动引用和解引用的功能。
当使用对象来调用方法时,Rust会自动为对象添加&
、&mut
或*
以便对象与方法签名匹配,即下面的代码是等价的:
mm.show(); //这种方法比较简洁 (&mm).show(); //这种方法稍微多了点东西
这种自动引用的行为之所以有效,是因为方法有一个明确的接收者———— self
的类型。在给出接收者和方法名的前提下,Rust 可以明确地计算出方法是仅仅读取(&self
),做出修改(&mut self
)或者是获取所有权(self
)。事实上,Rust 对方法接收者的隐式借用让所有权在实践中更友好。
//以下都是等效的,都可以修改age的值 mm.age = 19; (&mut mm).age = 89;
Rust 对方法接收者的隐式借用让所有权在实践中更友好。意思就是使用对象直接点操作就行了。
带参数的方法
因为方法和函数是类似的,所以在方法中也是可以传参的。
直接看一个例子就直接跳过了。
impl MM { //前面已经声明过MM的结构体了 fn eat(&self, food: &String) { println!("{}想吃{}", self.name, food); } } fn main() { let mm = MM { name: String::from("Alice"), age: 18, money: 100, }; mm.eat(&"手撕鸡".to_string()); }
结果:
Alice想吃手撕鸡
小结
结构体有意义的自定义类型。通过结构体,我们可以将相关联的数据片段联系起来并命名它们,这样可以使得代码更加清晰。在 impl
块中,你可以定义与你的类型相关联的函数,而方法是一种相关联的函数,让你指定结构体的实例所具有的行为。
但结构体并不是创建自定义类型的唯一方法:让我们转向 Rust 的枚举功能,为你的工具箱再添一个工具。
到此这篇关于Rust中的方法的文章就介绍到这了,更多相关Rust中的方法内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!