可視性

デフォルトでは、モジュール内の要素はプライベートですが、これはpubで修飾することでパブリックな属性にすることができます。パブリックな属性のみがモジュールの外のスコープからアクセスできます。

// `my_mod`という名前のモジュール
mod my_mod {
    // モジュール内の要素はデフォルトでプライベート。
    fn private_function() {
        println!("called `my_mod::private_function()`");
    }

    // `pub`を用いてパブリックに変更。
    pub fn function() {
        println!("called `my_mod::function()`");
    }

    // モジュール内からならば、プライベートな属性にアクセスできます。
    pub fn indirect_access() {
        print!("called `my_mod::indirect_access()`, that\n> ");
        private_function();
    }

    // モジュールもネストできます。
    pub mod nested {
        pub fn function() {
            println!("called `my_mod::nested::function()`");
        }

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

        // `pub(in path)`形式で宣言された関数は該当のパス内でのみアクセスできます。
        // `path`は親や先祖のモジュールでなくてはなりません。
        pub(in crate::my_mod) fn public_function_in_my_mod() {
            print!("called `my_mod::nested::public_function_in_my_mod()`, that\n> ");
            public_function_in_nested();
        }

        // `pub(self)`形式で宣言された関数は現在のモジュール内でのみアクセスできます。
        // つまり、プライベートにするのと同じです。
        pub(self) fn public_function_in_nested() {
            println!("called `my_mod::nested::public_function_in_nested()`");
        }

        // `pub(super)`形式で宣言された関数は親モジュール内でのみアクセスできます。
        pub(super) fn public_function_in_super_mod() {
            println!("called `my_mod::nested::public_function_in_super_mod()`");
        }
    }

    pub fn call_public_function_in_my_mod() {
        print!("called `my_mod::call_public_function_in_my_mod()`, that\n> ");
        nested::public_function_in_my_mod();
        print!("> ");
        nested::public_function_in_super_mod();
    }

    // pub(crate)により関数は現在のクレート内でのみアクセスできます。
    pub(crate) fn public_function_in_crate() {
        println!("called `my_mod::public_function_in_crate()`");
    }

    // ネストしたモジュールも、同様の性質を示します。
    mod private_nested {
        #[allow(dead_code)]
        pub fn function() {
            println!("called `my_mod::private_nested::function()`");
        }

        // 親がプライベートな場合、子要素がより大きなスコープでアクセスできるように宣言されていても、
        // 子要素にアクセス可能な範囲は制限されます。
        #[allow(dead_code)]
        pub(crate) fn restricted_function() {
            println!("called `my_mod::private_nested::restricted_function()`");
        }
    }
}

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

fn main() {
    // モジュールによって、同名の関数を区別することができます。
    function();
    my_mod::function();

    // パブリックな要素ならば、たとえネストしたものでも、
    // モジュールの外からアクセスすることができます。
    my_mod::indirect_access();
    my_mod::nested::function();
    my_mod::call_public_function_in_my_mod();

    // pub(crate)の要素は同じクレートのどこからでも呼び出すことができます。
    my_mod::public_function_in_crate();

    // pub(in path)の要素は指定されたモジュールからのみ呼び出すことができます。
    // エラー!`public_function_in_my_mod`関数はプライベート。
    //my_mod::nested::public_function_in_my_mod();
    // TODO ^ 試しにこの行をアンコメントしてみましょう。

    // プライベートな要素は、たとえパブリックなモジュール内に存在していても
    // 直接アクセスすることはできません。

    // エラー!`private_function`はプライベート。
    //my_mod::private_function();
    // TODO ^ 試しにこの行をアンコメントしてみましょう。

    // エラー!`private_function`はプライベート。
    //my_mod::nested::private_function();
    // TODO ^ 試しにこの行をアンコメントしてみましょう。

    // エラー!`private_nested`はプライベートなモジュール。
    //my_mod::private_nested::function();
    // TODO ^ 試しにこの行をアンコメントしてみましょう。

    // エラー!`private_nested`はプライベートなモジュール。
    //my_mod::private_nested::restricted_function();
    // TODO ^ 試しにこの行をアンコメントしてみましょう。
}