পাঠ ৭.৩

Module tree-তে item refer করার Path

Paths for Referring to an Item in the Module Tree

Module tree-তে কোনো item-কে refer করা — filesystem-এর path-এর মতো। দু'রকম form:

  • Absolute path — crate root থেকে; current crate-এর জন্য crate দিয়ে শুরু, external crate-এর জন্য crate-এর নাম দিয়ে।
  • Relative path — current module থেকে; self, super, বা current module-এর কোনো item-এর নাম দিয়ে।

দু'রকমেরই segment :: দিয়ে আলাদা।

দু'রকম path পাশাপাশি

src/lib.rsrust
mod front_of_house {
    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();
}

Absolute — crate দিয়ে শুরু (filesystem-এ /-এর মতো)। Relative — current scope-এ থাকা front_of_house দিয়ে শুরু।

সাধারণত absolute path বেশি ব্যবহার করা হয় — caller এবং item আলাদা জায়গায় move হলেও path break হয় না।

কিন্তু এটা compile হবে না — privacy

compile errortext
error[E0603]: module `hosting` is private
 --> src/lib.rs:9:28
  |
9 |     crate::front_of_house::hosting::add_to_waitlist();
  |                            ^^^^^^^  --------------- function `add_to_waitlist` is not publicly re-exported
  |                            |
  |                            private module

Rust-এ সব item default-এ private — function, method, struct, enum, module, constant সব। Parent module child-এর private item access করতে পারে না; কিন্তু child-রা ancestor-দের সব দেখতে পায় (কারণ child-রা parent-এর context-এর ভিতরে define হয়েছে)।

Restaurant analogy — back office private থাকে customer-দের কাছে, কিন্তু office manager পুরো restaurant দেখতে পান।

pub দিয়ে expose

প্রথম try — module-কে pub:

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

এখনো error — function-ও private:

compile errortext
error[E0603]: function `add_to_waitlist` is private

pub mod শুধু module-এ access দেয় — ভিতরের item-এ না। প্রতিটা item-কে আলাদা করে public করতে হয়:

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

pub fn eat_at_restaurant() {
    crate::front_of_house::hosting::add_to_waitlist();
    front_of_house::hosting::add_to_waitlist();
}

লক্ষ্য করো — front_of_house pub না, তবু eat_at_restaurant থেকে access করা যাচ্ছে। কারণ — দু'জন একই module-এ (crate root) sibling।

super:: — parent-এ যাওয়া

Filesystem-এর ..-এর মতো। Parent module-এ কিছু আছে — তাকে refer করতে:

fn deliver_order() {}

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

    fn cook_order() {}
}

back_of_house::fix_incorrect_order থেকে super:: যায় parent (crate root)-এ — সেখান থেকে deliver_order খুঁজে পায়।

Public struct — field-গুলো আলাদা

pub struct-এ struct public, কিন্তু field-গুলো default-এই private। প্রতিটা field আলাদা করে public/private করা যায়:

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);

    // meal.seasonal_fruit = String::from("blueberries"); // ERROR
}

toast public — read/write করা যায়। seasonal_fruit private — বাইরে থেকে touch করা যায় না।

এখানে একটা সমস্যা — Breakfast-এ একটা private field আছে, তাই বাইরে থেকে normal struct-syntax-এ instance create করা যাবে না। সেজন্য একটা public constructor (summer) লাগে।

Restaurant analogy — customer bread বেছে নিতে পারেন (toast public), কিন্তু কোন fruit আসবে chef-ই ঠিক করেন (seasonal_fruit private)।

Public enum — সব variant public

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;
}

pub enum দিলেই সব variant automatic public। প্রতিটাকে আলাদা pub করতে হয় না।

কেন এই default-difference?

Variant private হলে enum কাজে আসে না — প্রায় কোনো use case নেই। তাই default public।

Struct অনেক সময় শুধু internal data carry করে — field expose করার দরকার নেই। তাই default private, fine-grained control।

এই পাঠ থেকে যা শিখলে

  • Path — absolute (crate::...) বা relative (current module থেকে)।
  • সব default-এ private — child can see ancestors, but not vice versa।
  • pub mod — module-কে expose, কিন্তু ভিতরের item আলাদা করে pub করতে হয়।
  • super:: — parent module-এ access।
  • pub struct — struct public, field field-by-field। Private field থাকলে public constructor দরকার।
  • pub enum — সব variant automatic public।