iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 29
0
自我挑戰組

WebAssembly + Rust 的前端應用系列 第 29

[Day 29] Rust Modules (實作 Actix 後的說明以及補充 PART4)

還記得上一篇我們寫到一半的 Modules 介紹嗎?今天要來把剩下的部分給補完。

那麼就開始吧!

Exposing Paths with the pub Keyword

還記得 Rust 的物件預設都是 private 的這件事情嗎?這是上一次的範例所遇到的錯誤

$ cargo build
   Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0603]: module `hosting` is private
 --> src/lib.rs:9:28
  |
9 |     crate::front_of_house::hosting::add_to_waitlist();
  |                            ^^^^^^^

error[E0603]: module `hosting` is private
  --> src/lib.rs:12:21
   |
12 |     front_of_house::hosting::add_to_waitlist();
   |                     ^^^^^^^

因此我們就來改改看原本那支程式讓 hosting 變成 public 的試試看。

src/lib.rs

mod front_of_house {
    pub mod hosting {
        fn add_to_waitlist() {}
    }
}

pub fn eat_at_restaurant() {
    // Absolute path
    crate::front_of_house::hosting::add_to_waitlist();

    // Relative path
    front_of_house::hosting::add_to_waitlist();
}

結果還是錯的,

$ cargo build
   Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0603]: function `add_to_waitlist` is private
 --> src/lib.rs:9:37
  |
9 |     crate::front_of_house::hosting::add_to_waitlist();
  |                                     ^^^^^^^^^^^^^^^

error[E0603]: function `add_to_waitlist` is private
  --> src/lib.rs:12:30
   |
12 |     front_of_house::hosting::add_to_waitlist();
   |                              ^^^^^^^^^^^^^^^

原因是我們只有 public hosting 這個 module 但是裡面的內容仍然還是 private 的,若是我們想要取用到裡面的函式我們同樣要把他 public 出來。

src/lib.rs

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

pub fn eat_at_restaurant() {
    // Absolute path
    crate::front_of_house::hosting::add_to_waitlist();

    // Relative path
    front_of_house::hosting::add_to_waitlist();
}

這樣就會 work 了!

Starting Relative Paths with super

這邊的 super 在 path 的相對路徑裡面就等同於檔案系統的 .. 也就是上一層的意思,我們直接看一個範例吧。

src/lib.rs

fn serve_order() {}

mod back_of_house {
    fn fix_incorrect_order() {
        cook_order();
        super::serve_order();
    }

    fn cook_order() {}
}

back_of_house module 裡面的程式可以透過 super 先到上一層這邊也就是我們的 crate root 然後再拿到 serve_order 這支程式。

我們用檔案路徑來舉例應該會更清楚,

假如這是我當前的目錄 crate/back_of_house/ 然後我 cd .. 到上一層就變成 crate/ 然後我再 cd serve_order 就變成 crate/serve_order/

Making Structs and Enums Public

struct 和 enum(還沒寫到之後寫一下),也可以使用 pub 不過要注意的是 struct 的欄位並不會跟著一起 public 出去,舉例來說下面這支程式的 Breakfast 只有 toast 的欄位有被 public 出去而 seasonal_fruit 仍然是 private 的。

src/lib.rs

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() {
    // Order a breakfast in the summer with Rye toast
    let mut meal = back_of_house::Breakfast::summer("Rye");
    // Change our mind about what bread we'd like
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);

    // The next line won't compile if we uncomment it; we're not allowed
    // to see or modify the seasonal fruit that comes with the meal
    // meal.seasonal_fruit = String::from("blueberries");
}

上面這個例子我們可以看到 meal.toast 因為是 public 的所以可以修改但是 meal.seasonal_fruit 是 private 的所以編譯會報錯。

另外一個重點是我們必須在 back_of_house 的 module 裡面定義一支程式(這邊是 summer 這支程式)讓我們可以使用 Breakfast,否則因為 Breakfastseasonal_fruit 是 private 的欄位我們無法在外面宣告他,只能仰賴 summer 做這件事情。

反之若是我們 pub enum 則會全部都變成 public 的我們只需要宣告一次即可例如,

src/lib.rs

mod back_of_house {
    pub enum Appetizer {
        Soup,
        Salad,
    }
}

pub fn eat_at_restaurant() {
    let order1 = back_of_house::Appetizer::Soup;
    let order2 = back_of_house::Appetizer::Salad;
    // enum 不用替他的欄位宣告 pub 我想應該跟實作方式有關,但我還不想去翻 source code XD
}

上面的例子可以看到我把 Appetizer pub 之後就可以拿到他裡面的 SoupSalad 而不用另外宣告。

總結

今天把 pub 的概念都學完了不過其實我也只是縮短了官網的內容然後寫下來 XD,希望對已經不是程式菜鳥的各位有幫助,因為我有時候覺得官網太新手向廢話字有點多。

那麼下一篇的主題就是 use,雖然我們已經用得蠻多了不過還是可以再來順一次內容看看有沒有漏掉的。

以上是今天的內容鐵人賽雖然快結束了但是我會把繼續這個系列完成的,那麼我們明天見!

最後一樣有問題歡迎發問

/images/emoticon/emoticon07.gif

參考網址

ch07-03-paths-for-referring-to-an-item-in-the-module-tree


上一篇
[Day 28] Rust Modules (實作 Actix 後的說明以及補充 PART3)
下一篇
[Day 30] Rust Use (實作 Actix 後的說明以及補充 PART5)
系列文
WebAssembly + Rust 的前端應用30

1 則留言

0
wee911
iT邦新手 5 級 ‧ 2019-10-16 15:16:29

wasm 不写了吗?

這個系列寫完再看看XDD

我要留言

立即登入留言