RustCookbook(译):创建包和模块(第四章)

在本章中,我们将介绍以下配方:

  • 在Rust中定义一个模块
  • 构建嵌套模块
  • 使用struct创建模块
  • 控制模块
  • 访问模块
  • 创建文件层次结构
  • 在Rust中构建库
  • 调用外部包

介绍

本章重点介绍Rust中的模块和包。 它将帮助您开发高度模块化和生产级的Rust应用程序。 有了这个,您将拥有一个出色的文件层次结构,这将以模块化方式补充功能的开发。 本章中的配方还将帮助您在Rust中构建库,并通过外部程序定义,控制和访问功能。

在Rust中定义一个模块

所有应用程序必须模块化,以便易于维护和开发。 在Rust中,我们可以为我们的应用程序提供一个功能强大的模块系统,可以将应用程序源代码分层次地拆分为逻辑单元(我们称之为模块),并在整个应用程序中管理它们的可见性(公共/私有)。

模块的字典描述是它是项的集合,例如函数,结构,特征,impl块,甚至其他模块。

您将学习如何创建示例模块并了解此配方中可见性的概念。

做好准备

我们将要求Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为sample_mod.rs的文件,并在文本编辑器中将其打开。
2.使用相关信息编写代码头:

//-- #########################
//-- Task: To create a sample module to illustrate
how to use a module in rust
//-- Author: Vigneshwer.D
//-- Version: 1.0.0
//-- Date: 4 March 17
//-- #########################

3.使用mod关键字创建名为sample_mod的模块,并在其中定义名为private_function的函数:

// Defined module named `sample_mod`(定义的模块名   `sample_mod`)
mod sample_mod {
// By default all the items in module have private visibility(默认情况下,模块中的所有项都具有私有可见性)
fn private_function() {
	println!("called `sample_mod::private_function()` \n");
}

4.使用模块中的pub关键字,通过将其可见性标记为public来定义名为sample_function的函数:

// Using the `pub` keyword changes it visibility to public(使用`pub`关键字将其可见性更改为public)
pub fn sample_function() {
	println!("called `sample_mod::sample_function()` \n");
}

5.声明一个公共函数indirect_private_fn,它将调用private_function:

// Public items of the module can access the private visible items(模块的公共项可以访问私有可见项)
pub fn indirect_private_fn() {
	print!("called `sample_mod::indirect_access()`, that \n ");
	private_function();
}
}

6.在sample_mod模块的范围之外定义sample_function:

// Created a sample function to illustrate calling of(创建了一个示例函数来说明调用)
fn sample_function() {
	println!("Called the `sample_function()` which is not a part of mod `sample_mod` \n");
}

7.声明main函数,我们将在其中调用sample_mod模块的每个项目以了解它们的工作方式并打印输出:

// Execution of the program starts from here(程序的执行从这里开始)
fn main() {
// Calling the sample_function which is outside module(调用模块外部的sample_function)
sample_function();
// Calling the public visible sample_mod's sample_function(调用public可见的sample_mod的sample_function)
sample_mod::sample_function();
	// Accessing the private function indirectly
	sample_mod::indirect_private_fn();
	// Error! `private_function` is private
	//sample_mod::private_function(); // TODO ^ Try uncommenting this line
}

在正确设置上述代码后,您应该在编译和运行程序时获得以下屏幕截图输出:
在这里插入图片描述

怎么运行的…

在本文中,您学习了如何在Rust中创建示例模块以及如何调用模块中的项目。

从本章开始,我们将遵循标题样式,这是我们的第一步。 它基本上描述了应用程序单元的代码或部分功能。 这是一个非常好的代码实践,因为它有助于另一个人从你开发的地方开始。

我们使用mod关键字创建了一个名为sample_mod的模块,然后是大括号{}。 模块的内容是它的项目。 每个项目都旨在执行特定任务。 默认情况下,模块中的所有项都具有私有可见性,这意味着无法直接在范围外访问它们。 在sample_mod模块中,我们使用pub关键字显式创建了两个具有公共可见性的函数。 我们在使用fn关键字创建或声明函数之前添加了关键字。 这使项目在模块范围之外公开可见。 可以在模块范围内访问私有函数或项目,其中所有项目可以相互调用,因此我们可以间接调用公共项目以从中访问私有项目。

我们在此代码中创建了四个函数,其中三个在模块内部,一个可以全局访问。 我们在sample_mod中创建的第一个函数是private_function,默认情况下,它具有私有可见性。 然后我们创建了两个公共函数,即sample_function和indirect_private_fn,其中indirect_private_fn在其体内调用private_function

要在其范围之外调用模块的项,我们必须遵循特定的语法-module_name :: publically_visible_function名称。 在main函数中,我们调用sample_fucntion(它是常规函数)和sample_mode模块的两个公开可见项:function sample_mod :: sample_function()和sample_mod :: indirect_private_fn()。 这些项目将执行各自范围内的内容。

在调用模块的私有项时,它将抛出一个错误,指出特定项是私有的。 例如,在前面的配方中,当我们直接调用sample_mod :: private_function()时,我们得到了一个错误; 从主要功能。

构建嵌套模块

嵌套模块是我们希望模块内部具有模块,执行不同任务的地方。 您将学习如何声明和访问嵌套模块的项目。

嵌套模块是将应用程序中的类似项或功能单元放在一起的好方法,这有助于维护功能和调试崩溃。

做好准备

我们将要求Rust编译器和任何文本编辑器进行编码。

怎么做…

1.在项目工作区中创建名为sample_nested.rs的文件
2.编写代码头信息,它将提供代码的概述:

//-- #########################
//-- Task: To create a sample nested_mod module
//-- Author: Vigneshwer.D
//-- Version: 1.0.0
//-- Date: 4 March 17
//-- #########################

3.使用mod关键字创建名为sample_mod的模块:

// Defined module named `sample_mod`(定义的模块名为`sample_mod`)
mod sample_mod {

4.在sample_mod模块下创建另一个名为nested_mod的模块,其中包含函数和公共可见性,这使得sample_mod成为嵌套模块:

// Defined public Nested module named `nested_mod`(定义名为`nested_mod`的公共嵌套模块)
pub mod nested_mod {
	pub fn function() {
		println!("called `sample_mod::nested_mod::function()`");
	}

5.在nested_mod模块下创建一个名为private_function的函数:

#[allow(dead_code)]
fn private_function() {
	println!("called `sample_mod::nested_mod::private_function()`");
} }

6.使用sample_mod中名为function的公共函数定义另一个名为private_nested_mod的模块:

// Nested modules follow the same rules for visibility
mod private_nested_mod {
#[allow(dead_code)]
pub fn function() {
println!("called
`sample_mod::private_nested_mod::function()`");
}
} }

7.定义main函数并使用其中声明的不同项调用嵌套模块:

// Execution starts

fn main() {
sample_mod::nested_mod::function();
// Private items of a module cannot be directly accessed,even if nested_mod in a public module
// Error! `private_function` is private
//sample_mod::nested_mod::private_function(); // TODO ^ Try
uncommenting this line
// Error! `private_nested_mod` is a private module
//sample_mod::private_nested_mod::function(); // TODO ^ Try
uncommenting this line
}

正确设置上述代码后,在编译和运行程序时应该得到以下输出:
在这里插入图片描述

怎么运行的…

嵌套模块是一个在另一个模块中有一个模块的概念。 此功能有助于将一组应用程序单元放置在公共标头内。

在这个配方中,我们使用mod关键字创建了一个名为sample_mod的模块; 在这个模块中,我们创建了另外两个模块,即nested_mod和private_nested_mod,具有不同的可见性。 模块可见性的规则遵循与模块项相同的规则:我们必须明确提及pub关键字以提及模块的可见性。 如果我们不提及任何内容,Rust编译器将认为它是私有的。

然后,我们在嵌套模块中创建项目,这些模块位于sample_mod模块下。 在nested_mod(一个公共嵌套模块)中,我们创建了两个项:名为function的公共方法和名为private_function的私有方法。 在另一个私有嵌套模块private_nested_mod中,我们创建了一个名为function的公共方法。

在main函数中,我们调用遵循标准语法的相应项来访问项。 这里唯一的区别是项目驻留在不同的嵌套模块中。 在这种情况下,我们遵循module_name :: nested_module_name:item name语法。 在这里,我们首先调用模块名称,然后是嵌套模块名称及其项目。

我们将公共嵌套模块称为公共项,即sample_mod :: nested_mod :: function()。 它将运行正常并执行项目的内容。 在调用私有嵌套模块(在我们的配方中是sample_mod :: nested_mod :: private_function),以及公共嵌套模块的类似私有项(在我们的配方中是sample_mod :: private_nested_mod :: function)时,我们将得到一个错误 提到这些项目是私有的,因为私人可见的单位不能在范围之外直接访问。

我们在private_nested_mod模块中有item函数的#[allow(dead_code)]属性。 这个想法是禁用编译器的dead_code lint,它将警告未使用的函数。 简单来说,lint是标记代码中的错误的软件。

对于驻留在不同模块中的项目/单元,我们可以使用相同的名称。 在前面的配方中,我们有一个名为function的项,它存在于两个嵌套模块中。

使用struct创建模块

此配方涵盖了对其字段具有额外可见性的结构。 可见性默认为private,可以使用pub修饰符覆盖。 这种可见性仅在从模块外部访问结构时才有意义,在结构中定义结构并且目标是隐藏信息(封装)。

做好准备

我们将要求Rust编译器和任何文本编辑器进行编码。

怎么做…

1.在项目工作区中创建名为sample_struct.rs的文件

2.使用代码的详细信息编写代码头:

//-- #########################
//-- Task: To create a sample nested_mod module
//-- Author: Vigneshwer.D
//-- Version: 1.0.0
//-- Date: 4 March 17
//-- #########################

3.创建一个名为sample_struct的示例模块,您可以在其中声明一个名为WhiteBox的公共结构:

// Sample module which has struct item(具有struct项的示例模块)
mod sample_struct {
// A public struct with a public field of generic type `T`(具有泛型类型`T`的公共字段的公共结构)
	pub struct WhiteBox<T> {
		pub information: T,
}

4.使用私有泛型类型T声明名为BlackBox的公共结构:

// A public struct with a private field of generic type `T`(具有泛型类型`T`的私有字段的公共结构)
#[allow(dead_code)]
pub struct BlackBox<T> {
	information: T,
}

5.使用impl关键字创建一个名为const_new的公共构造函数,该关键字将泛型T类型作为输入:

impl<T> BlackBox<T> {
	// A public constructor method(公共构造函数方法)
	pub fn const_new(information: T) -> BlackBox<T> {
		BlackBox {
			information: information,
		}
	}
} }

6.通过调用thesample_struct模块的结构项来声明main函数,该模块是whitebox结构项:

// Execution starts here
fn main() {
	// Public structs with public fields can be constructed as usual
	let white_box = sample_struct::WhiteBox { information: "public information n" };

	// and their fields can be normally accessed.
	println!("The white box contains: {} \n", white_box.information);
	// Public structs with private fields cannot be constructed using field names.
	// Error! `BlackBox` has private fields
	//let black_box = sample_struct::BlackBox { information: "classified information" };
	// TODO ^ Try uncommenting this line
	// However, structs with private fields can be created using
	// public constructors
	let _black_box = sample_struct::BlackBox::const_new("classified
information \n");
	// and the private fields of a public struct cannot be accessed.
	// Error! The `information` field is private
	//println!("The black box contains: {}",
	_black_box.information);
	// TODO ^ Try uncommenting this line
}

正确设置上述代码后,在编译和运行程序时应该得到以下输出:

在这里插入图片描述

怎么运行的…

到目前为止,在前面的配方中,我们只研究具有充当其项目功能的模块。 在这个配方中,我们将创建对其字段具有额外可见性的结构项。

默认情况下,可见性是私有的,可以使用pub关键字进行更改。 当我们尝试访问模块范围之外的模块时,可见性允许我们隐藏信息。

我们使用mod关键字创建了一个名为sample_struct的模块。 我们使用pub和struct关键字创建了两个具有公共可见性的结构,名为WhiteBox和BlackBox。 在这两个结构项中,我们都有一个通用类型T.

在Rust中,泛型意味着特定单元可以接受一个或多个泛型类型参数。 例如,考虑fn foo (T){…}。 这里,T是使用指定为泛型类型参数的参数,它允许它接受任何类型的任何参数。

在这两个结构中,我们有一个名为information的字段,它与T绑定,这是我们收到的参数。 唯一的区别是我们提到WhiteBox中的信息在结构中是公共的,而BlackBox中的信息默认为私有。

接下来,我们为BlackBox创建了一个实现块,我们在impl块中明确指定了泛型类型T. 在其中,我们创建了一个名为const_new的方法,我们公开显示它,它接受泛型类型T作为参数并返回一个BlackBox结构。 const_new充当BlackBox的公共构造函数,我们想在其中创建数据类型。

在主块中,我们首先创建了WhiteBox结构,并通过sample_struct :: WhiteBox {information:“public information \ n”}将其分配给名为white_box的变量。 在这里,我们调用模块,创建一个复杂的数据结构并打印white_box,信息字段,这是在前面的步骤中提供的。 接下来,我们尝试以类似的方式创建一个具有BlackBox数据结构的变量。 这导致错误说字段名称是私有的。 这就是为什么我们创建了一个公共方法const_new,它是BlackBox数据类型的构造函数。 我们通过sample_struct :: BlackBox :: const_new(“分类信息\ n”)执行此步骤并将其分配给_black_box。

这将参数从main传递到impl块并创建了结构。 通过这种方式,我们能够使用私有字段定义公共结构,但我们仍然无法通过_black_box.information公开访问信息字段,因为它最初是一个私有字段。

可以通过模块中的间接方法访问私有成员。 请考虑以下代码段:

pub mod root {
	use self::foo::create_foo;
	mod foo {
		pub struct Foo {
		i: i32,
	} 
	impl Foo{
		pub fn hello_foo(&self){
		println!("Hello foo");
	}
} 
	pub fn create_foo(i: i32) -> Foo{
		Foo { i: i }
	}
}
 pub mod bar {
		pub struct Bar {
		pub f: ::root::foo::Foo,
} 
impl Bar {
		pub fn new(i: i32) -> Self {
		Bar { f: ::root::foo::create_foo(i) }
}
}
}
} 

fn main() {
	//still private
	//let f = root::foo::create_foo(42);
	let b = root::bar::Bar::new(42);
	b.f.hello_foo();
}

我们在foo模块中公开了一个公共构造函数create_foo,但模块foo仍然是私有的,我们只用use关键字在root中公开create_foo,这意味着bar现在可以创建一个Foo结构但是create_foo在root之外仍然是私有的。

控制模块

本文重点介绍Rust模块中use关键字的用法,这将有助于将冗长且繁琐的模块调用路径绑定到一个简单的单个实体。 这将提高代码可读性,并为开发人员调用模块单元提供更多控制。 我们还将介绍使用范围和阴影的概念。

做好准备

我们将要求Rust编译器和任何文本编辑器进行编码。

怎么做…

1.在项目工作区中创建名为sample_control.rs的文件。

2.使用代码的详细信息编写代码头:

//-- #########################
//-- Task: To create a sample module to illustrating `use`
//-- Author: Vigneshwer.D
//-- Version: 1.0.0
//-- Date: 4 March 17
//-- #########################

3.使用use关键字创建other_function,以便为deep模块的项创建绑定:

// Bind the `deeply::nested::function` path to
`other_function`.
use deeply::nested::sample_function as other_function;

4.使用包含公共函数sample_function的名为nested的嵌套模块深度声明嵌套模块:

// Defined a nested
mod deeply {
pub mod nested {
pub fn sample_function() {
println!("called `deeply::nested::function()` \n")
}
}
}

5.创建一个名为sample_function的函数:

fn sample_function() {
println!("called `function()` \n");
}

6.通过调用other_function声明main函数:

fn main() {
// Easier access to `deeply::nested::function`
other_function();

7.创建一个块。 在这个块中,使用use关键字并声明deep :: nested :: sample_function,这相当于将它绑定到sample_function:

println!("Entering a block n");
{
// This is equivalent to `use deeply::nested::sample_function
as sample_function`.
// This `sample_function()` will shadow the outer one.
use deeply::nested::sample_function;
sample_function();
// `use` bindings have a local scope. In this case, the
// shadowing of `function()` is only in this block.
println!("Leaving the block \n");
}

8.在创建的块之外调用sample_function:

sample_function();
}

正确设置上述代码后,您应该获得以下输出
当你编译并运行程序时:

在这里插入图片描述

怎么运行的…

我们专注于这个配方中的use关键字,当你的模块变得更深时(这意味着有很多嵌套的模块和单元),这非常方便。 简而言之,use有助于将长模块调用绑定到单个名称。 在前面的配方中,我们有一个名为deep的嵌套模块,其中嵌套是深入的模块,它具有名为sample_function的公共函数。 通常,我们可以通过deep :: nested :: sample_function来调用这个函数; 但是,使用use关键字,我们可以将它绑定到单个实体并在main函数中调用它,这样可以更容易地访问它。 在这里,我们将此路径绑定到other_function(),并且我们还创建了一个名为sample_function的普通函数来理解阴影的概念。

我们在main函数中创建了一个块,并明确提到使用deep :: nested :: sample_function。 之后我们也调用了sample_function。 这会调用deep模块的sample_function项而不是全局可用的函数,并且一旦超出范围,块中提到的用法就会结束。 在块外部调用sample_function将导致调用全局函数,因为use不再处于活动状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值