Rust 組織管理

任何一門編程語言如果不能組織代碼都是難以深入的,幾乎沒有一個軟件產(chǎn)品是由一個源文件編譯而成的。

本教程到目前為止所有的程序都是在一個文件中編寫的,主要是為了方便學習 Rust 語言的語法和概念。

對于一個工程來講,組織代碼是十分重要的。

Rust 中有三個重要的組織概念:箱、包、模塊。

箱(Crate)

"箱"是二進制程序文件或者庫文件,存在于"包"中。

"箱"是樹狀結(jié)構(gòu)的,它的樹根是編譯器開始運行時編譯的源文件所編譯的程序。

注意:"二進制程序文件"不一定是"二進制可執(zhí)行文件",只能確定是是包含目標機器語言的文件,文件格式隨編譯環(huán)境的不同而不同。

包(Package)

當我們使用 Cargo 執(zhí)行 new 命令創(chuàng)建 Rust 工程時,工程目錄下會建立一個 Cargo.toml 文件。工程的實質(zhì)就是一個包,包必須由一個 Cargo.toml 文件來管理,該文件描述了包的基本信息以及依賴項。

一個包最多包含一個庫"箱",可以包含任意數(shù)量的二進制"箱",但是至少包含一個"箱"(不管是庫還是二進制"箱")。

當使用 cargo new 命令創(chuàng)建完包之后,src 目錄下會生成一個 main.rs 源文件,Cargo 默認這個文件為二進制箱的根,編譯之后的二進制箱將與包名相同。

模塊(Module)

對于一個軟件工程來說,我們往往按照所使用的編程語言的組織規(guī)范來進行組織,組織模塊的主要結(jié)構(gòu)往往是樹。Java 組織功能模塊的主要單位是類,而 JavaScript 組織模塊的主要方式是 function。

這些先進的語言的組織單位可以層層包含,就像文件系統(tǒng)的目錄結(jié)構(gòu)一樣。Rust 中的組織單位是模塊(Module)。

mod nation {
    mod government {
        fn govern() {}
    }
    mod congress {
        fn legislate() {}
    }
    mod court {
        fn judicial() {}
    }
}

這是一段描述法治國家的程序:國家(nation)包括政府(government)、議會(congress)和法院(court),分別有行政、立法和司法的功能。我們可以把它轉(zhuǎn)換成樹狀結(jié)構(gòu):

nation
 ├── government
 │ └── govern
 ├── congress
 │ └── legislate
 └── court
   └── judicial

在文件系統(tǒng)中,目錄結(jié)構(gòu)往往以斜杠在路徑字符串中表示對象的位置,Rust 中的路徑分隔符是 :: 。

路徑分為絕對路徑和相對路徑。絕對路徑從 crate 關(guān)鍵字開始描述。相對路徑從 self 或 super 關(guān)鍵字或一個標識符開始描述。例如:

crate::nation::government::govern();

是描述 govern 函數(shù)的絕對路徑,相對路徑可以表示為:

nation::government::govern();

現(xiàn)在你可以嘗試在一個源程序里定義類似的模塊結(jié)構(gòu)并在主函數(shù)中使用路徑。

如果你這樣做,你一定會發(fā)現(xiàn)它不正確的地方:government 模塊和其中的函數(shù)都是私有(private)的,你不被允許訪問它們。

訪問權(quán)限

Rust 中有兩種簡單的訪問權(quán):公共(public)和私有(private)。

默認情況下,如果不加修飾符,模塊中的成員訪問權(quán)將是私有的。

如果想使用公共權(quán)限,需要使用 pub 關(guān)鍵字。

對于私有的模塊,只有在與其平級的位置或下級的位置才能訪問,不能從其外部訪問。

mod nation {
    pub mod government {
        pub fn govern() {}
    }

    mod congress {
        pub fn legislate() {}
    }
    
    mod court {
        fn judicial() {
            super::congress::legislate();
        }
    }
}

fn main() {
    nation::government::govern();
}

這段程序是能通過編譯的。請注意觀察 court 模塊中 super 的訪問方法。

如果模塊中定義了結(jié)構(gòu)體,結(jié)構(gòu)體除了其本身是私有的以外,其字段也默認是私有的。所以如果想使用模塊中的結(jié)構(gòu)體以及其字段,需要 pub 聲明:

mod back_of_house {
    pub struct Breakfast {
        pub toast: String,
        seasonal_fruit: String,
    }

    impl Breakfast {
        pub fn summer(toast: &str) -> Breakfast {
            Breakfast {
                toast: String::from(toast),
                seasonal_fruit: String::from("peaches"),
            }
        }
    }
}
pub fn eat_at_restaurant() {
    let mut meal = back_of_house::Breakfast::summer("Rye");
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);
}
fn main() {
    eat_at_restaurant()
}

運行結(jié)果:

I'd like Wheat toast please

枚舉類枚舉項可以內(nèi)含字段,但不具備類似的性質(zhì):

mod SomeModule {
    pub enum Person {
        King {
            name: String
        },
        Quene
    }
}

fn main() {
    let person = SomeModule::Person::King{
        name: String::from("Blue")
    };
    match person {
        SomeModule::Person::King {name} => {
            println!("{}", name);
        }
        _ => {}
    }
}

運行結(jié)果:

Blue

難以發(fā)現(xiàn)的模塊

使用過 Java 的開發(fā)者在編程時往往非常討厭最外層的 class 塊——它的名字與文件名一模一樣,因為它就表示文件容器,盡管它很繁瑣但我們不得不寫一遍來強調(diào)"這個類是文件所包含的類"。

不過這樣有一些好處:起碼它讓開發(fā)者明明白白的意識到了類包裝的存在,而且可以明確的描述類的繼承關(guān)系。

在 Rust 中,模塊就像是 Java 中的類包裝,但是文件一開頭就可以寫一個主函數(shù),這該如何解釋呢?

每一個 Rust 文件的內(nèi)容都是一個"難以發(fā)現(xiàn)"的模塊。

讓我們用兩個文件來揭示這一點:

main.rs 文件

// main.rs
mod second_module;
fn main() {
    println!("This is the main module.");
    println!("{}", second_module::message());
}

second_module.rs 文件

// second_module.rs
pub fn message() -> String {
    String::from("This is the 2nd module.")
}

運行結(jié)果:

This is the main module.
This is the 2nd module.

use 關(guān)鍵字

use 關(guān)鍵字能夠?qū)⒛K標識符引入當前作用域:

mod nation {
    pub mod government {
        pub fn govern() {}
    }
}

use crate::nation::government::govern;

fn main() {
    govern();
}

這段程序能夠通過編譯。

因為 use 關(guān)鍵字把 govern 標識符導(dǎo)入到了當前的模塊下,可以直接使用。

這樣就解決了局部模塊路徑過長的問題。

當然,有些情況下存在兩個相同的名稱,且同樣需要導(dǎo)入,我們可以使用 as 關(guān)鍵字為標識符添加別名:

mod nation {
    pub mod government {
        pub fn govern() {}
    }
    pub fn govern() {}
}
    
use crate::nation::government::govern;
use crate::nation::govern as nation_govern;

fn main() {
    nation_govern();
    govern();
}

這里有兩個 govern 函數(shù),一個是 nation 下的,一個是 government 下的,我們用 as 將 nation 下的取別名 nation_govern。兩個名稱可以同時使用。

use 關(guān)鍵字可以與 pub 關(guān)鍵字配合使用:

mod nation {
    pub mod government {
        pub fn govern() {}
    }
    pub use government::govern;
}

fn main() {
    nation::govern();
}

引用標準庫

Rust 官方標準庫字典:https://doc.rust-lang.org/stable/std/all.html

在學習了本章的概念之后,我們可以輕松的導(dǎo)入系統(tǒng)庫來方便的開發(fā)程序了:

use std::f64::consts::PI;

fn main() {
    println!("{}", (PI / 2.0).sin());
}

運行結(jié)果:

1

所有的系統(tǒng)庫模塊都是被默認導(dǎo)入的,所以在使用的時候只需要使用 use 關(guān)鍵字簡化路徑就可以方便的使用了。

丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清