• Rust包和crate以及模块


    概念

      crate 是一个二进制项或者库。crate root 是一个源文件,Rust 编译器以它为起始点,并构成你的 crate 的根模块(我们将在 “DefiningModules to Control Scope and Privacy” 一节深入解读)。包(package) 是提供一系列功能的一个或者多个 crate。一个包会包含有一个 Cargo.toml 文件,阐述如何去构建这些 crate。包中所包含的内容由几条规则来确立。一个包中至多 只能 包含一个库 crate(library crate);包中可以包含任意多个二进制 crate(binary crate);包中至少包含一个 crate,无论是库的还是二进制的。

    $ cargo new my-project 
        Created binary (application) `my-project` package 
    
    $ ls my-project 
            Cargo.toml 
            src 
    $ ls my-project/src 
            main.rs                
    

      当我们输入了这条命令,Cargo 会给我们的包创建一个 Cargo.toml 文件。查看 Cargo.toml 的内容,会发现并没有提到 src/main.rs,因为 Cargo 遵循的一个约定:src/main.rs 就是一个与包同名的二进制 crate 的 crate 根。同样的,Cargo 知道如果包目录中包含 src/lib.rs,则包带有与其同名的库 crate,且 src/lib.rs 是 crate 根。crate 根文件将由 Cargo 传递给 rustc 来实际构建库或者二进制项目。在此,我们有了一个只包含 src/main.rs 的包,意味着它只含有一个名为 my-project 的二进制 crate。如果一个包同时含有 src/main.rs 和 src/lib.rs,则它有两个 crate:一个库和一个二进制项,且名字都与包相同。通过将文件放在 src/bin 目录下,一个包可以拥有多个二进制crate:每个 src/bin 下的文件都会被编译成一个独立的二进制 crate。

      因为一个 crate 的功能是在自身的作用域进行命名的,当我们将 rand 作为一个依赖,编译器不会混淆 Rng 这个名字的指向。在我们的 crate 中,它指向的是我们自己定义的struct Rng 。我们可以通过 rand::Rng 这一方式来访问 rand crate 中的 Rng 特性。
     
    定义模块来控制作用域与私有性
      我们会从下面几个方面讲:允许你命名项的 路径(paths);用来将路径引入作用域的 use 关键字;以及使项变为公有的 pub 关键字。我们还将讨论 as 关键字、外部包和 glob 运算符。现在,让我们把注意力放在模块上!
     
    模块
      模块 让我们可以将一个 crate 中的代码进行分组,以提高可读性与重用性。模块还可以控制项的 私有性,即项是可以被外部代码使用的(public),还是作为一个内部实现的内容,不能
    被外部代码使用(private)。
      在餐饮业,餐馆中会有一些地方被称之为 前台(front of house),还有另外一些地方被称之为 后台(back of house)。前台是招待顾客的地方,在这里,店主可以为顾客安排座位,服务员接受顾客下单和付款,调酒师会制作饮品。后台则是由厨师工作的厨房,洗碗工的工作地点,以及经理做行政工作的地方组成。
      我们可以将函数放置到嵌套的模块中,来使我们的 crate 结构与实际的餐厅结构相同。通过执行 cargo new --lib restaurant ,来创建一个新的名为 restaurant 的库。然后将示例 7-1 中所罗列出来的代码放入 src/lib.rs 中,来定义一些模块和函数。
    mod front {
        //  使用mod来定义模块,里面包含两个模块,其中里面有一些自定义的功能函数
        mod hosting {
            fn add_waitlist() {}
            fn seat_at_table() {} //  模块还可以保存一些定义的其他项,比如结构体定义模块来控制作用域与私有性 构体、枚举、常量、特性、或者函数
        }
    
        mod serving {   // 使用模块,我们可以将相关的定义分组到一起,并指出他们为什么相关
            fn take_order() {}
            fn server_order() {}
            fn take_payment() {}
        }
    }
    

      在前面我们提到了, src/main.rs 和 src/lib.rs 叫做 crate 根。之所以这样叫它们的原因是,这两个文件的内容都是一个从名为 crate 的模块作为根的 crate 模块结构,称为 模块树(module tree)。这个树展示了一些模块是如何被嵌入到另一个模块的(例如, hosting 嵌套在front_of_house 中)。这个树还展示了一些模块是互为 兄弟(siblings) 的,那如果A模块包含B模块则,A模块称为父模块,B称为子模块

     
    路径用于引用模块树中的项
      路径有两种形式:
        绝对路径(absolute path)从 crate 根开始,以 crate 名或者字面值 crate 开头。
        相对路径(relative path)从当前模块开始,以 self 、 super 或当前模块的标识符开头。
      绝对路径和相对路径都后跟一个或多个由双冒号( :: )分割的标识符。让我们来看看如何调用一个模块中的函数使用路径:
    mod front_of_house {
        mod hosting {
            fn add_to_waitlist() {}
        }
    }
    
    pub fn eat_at_restaurant() {  // 一个 公共API,所以我们使用 pub 关键字来标记它,是他暴露
        // 绝对路径
        crate::front_of_house::hosting::add_to_waitlist(); // add_to_waitlist 函数与 eat_at_restaurant 被定义在同一 crate 中,这意味着我们可以 使用 crate 关键字为起始的绝对路径。
    
        // 相对路径
        front_of_house::hosting::add_to_waitlist();
    }
    

      接下来让我们编译(cargo build) 下上面的代码,会出现如下报错:front_of_house::hosting::add_to_waitlist(); ^^^^^^^ private module; 也就是说路径是没问题的,但是 Rust 不让我们使用,因为它不能访问私有片段,Rust 中默认所有项(函数、方法、结构体、枚举、模块和常量)都是私有的。父模块中的项不能使用子模块中的私有项,但是子模块中的项可以使用他们父模块中的项。这是因为子模块封装并隐藏了他们的实现详情,但是子模块可以看到他们定义的上下文。继续拿餐馆作比喻,把私有性规则想象成餐馆的后台办公室:餐馆内的事务对餐厅顾客来说是不可知的,但办公室经理可以洞悉其经营的餐厅并在其中做任何事情。你还可以通过使用 pub 关键字来创建公共项,使子模块的内部部分暴露给上级模块。

     
    使用 pub 关键字暴露路径
      也就是说由于Rust的私有性,要求模块内部的内容要被外部访问就必须使用pub来暴露。
    mod front_of_house {
        pub mod hosting {
            // mod hosting前添加了pub关键字,使其变成公有的
            pub fn add_to_waitlist() {} // 如果我们可以访问 front_of_house ,那我们也可以访问 hosting 。但是 hosting 的 内容 (contents) 仍然是私有的;这表明使模块公有并不使其内容也是公有的。模块上的 pub 关键字只允许其父模块引用它。
        }
    }
    
    pub fn eat_at_restaurant() {
        // 一个 公共API,所以我们使用 pub 关键字来标记它,是他暴露
        // 绝对路径
        crate::front_of_house::hosting::add_to_waitlist(); // add_to_waitlist 函数与 eat_at_restaurant 被定义在同一 crate 中,这意味着我们可以 使用 crate 关键字为起始的绝对路径。
    
        // 相对路径
        front_of_house::hosting::add_to_waitlist();
    }
    

      

     
  • 相关阅读:
    xampp 80端口被占用后这么办??解决了
    XAMPP配置基于虚拟目录、多域名的环境
    mysql 主从同步
    jquery插件
    Css绘制箭头实现代码
    Ubuntu下mount命令的好用处
    linux下IPTABLES配置详解
    java程序员网站
    1.Hibernate介绍
    1. Mybatis介绍
  • 原文地址:https://www.cnblogs.com/double-W/p/13175343.html
Copyright © 2020-2023  润新知