【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
7.2.1. 路径的简介
在Rust里,如果想要找到模块里的某个东西,就必须知道并使用它的路径。Rust中的路径就跟文件系统里面的了路径是差不多的,与其他语言里的命名空间有点像。
路径一共有两种形式:
- 绝对路径:从crate库开始,使用crate名或字面值crate(看下面的例子就明白了)
- 相对路径:从当前模块开始,使用self(本身),super(上一级)或者当前模块的标识符
路径至少由一个标识符组成,标识符之间使用::
连接
7.2.2. 路径的使用
看个例子(lib.rs
):
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
}
pub fn eat_at_restaurant(){
crate::front_of_house::hosting::add_to_waitlist();
front_of_house::hosting::add_to_waitlist();
}
hosting
是front_of_the_house
的子module,hosting
下还定义了两个函数add_to_waitlist
和seat_at_table
。
在front_of_the_house
的同一级中还声明了一个函数eat_at_restaurant
,这个函数下就分别用绝对路径和相对路径调用了add_to_waitlist
这个函数。
对于绝对路径,函数eat_at_restaurant
与add_to_waitlist
所在的front_of_the_house
模块在同一个文件lib.rs
里,也就是在同一个crate里(lib.rs
的内容已经隐式地组成了crate这个模块,具体可以参考上一篇文章最后一部分)。所以说绝对路径就是从crate
开始写起,逐级地写,用::
分开每级的标识符:
crate::front_of_house::hosting::add_to_waitlist();
对于相对路径,由于函数eat_at_restaurant
与add_to_waitlist
所在的front_of_the_house
模块在同一级,所以就可以直接从模块名起手写,依然是逐级地写,用::
分开每级的标识符:
front_of_house::hosting::add_to_waitlist();
在实际项目中,使用绝对路径还是相对路径主要取决于你定义条目的代码(例子中的add_to_waitlist
)和使用条目的代码(例子中的eat_at_restaurant
)会不会一起移动而决定。如果这两部分一起移动,也就是两者的相对路径不会变,那么就使用相对路径;反之则需要用绝对路径。但大部分情况还是使用绝对路径,因为这样定义条目的代码和使用条目的代码就可以彼此独立地进行移动。
接下来我们运行一下代码:
error[E0603]:module `hosting` is private
不管是绝对路径调用还是相对路径调用都报了这个错误。这个错误的意思是hosting
模块是私有的。
刚好借着这个报错讲一下私有边界这个概念
7.2.3. 私有边界(Privacy boundary)
模块的作用不仅是组织代码,还可以定义私有边界。如果想把函数或struct
设为私有的就可以把它放到某个模块中,就像刚才那个例子中的函数一样,它就在hosting
这个模块里。
Rust默认所有的条目(函数、方法、struct、enum、模块、常量等)都是私有的。而对于私有的条目来说,外部的代码就无法调用或者是依赖他们。Rust之所以这么规定是因为它希望这些内部细节默认隐藏来使程序员明确地知道修改哪些内部实现不会破话外部的代码。
Rust的私有边界还有规则:父级模块无法访问子模块中的私有条目,依然是为了隐藏实现细节;在子模块里可以使用所有祖先模块中的条目,因为子模块就是定义于父模块以及其他祖先模块的上下文中。打个比方:爸爸不能看儿子日记,而儿子可以用爸爸的钱。
想要公有就需要在定义模块时加上pub
关键字。
7.2.4. pub
关键字
在mod
关键字之前加上pub
即可以把模块转为公有。在之前的代码例上稍作修改:
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
fn seat_at_table() {}
}
}
pub fn eat_at_restaurant(){
crate::front_of_house::hosting::add_to_waitlist();
front_of_house::hosting::add_to_waitlist();
}
注意:hosting
这个模块和add_to_waitlist()
这个函数的前面都需要加pub
关键字
再进行编译,这下编译器没有报错。
有人可能会问:为什么front_of_house
没有加pub
是私有的但调用时没有报错呢?这是因为它是文件里的根级,而根级和根级之间是可以相互调用的,无论是私有的还是公有的。