🔖

Rust pub(crate) の基本

に公開

pub(crate) の基本

Rust では、アイテム(関数、構造体、モジュール、マクロなど)の公開範囲を柔軟に指定できます。その中でも pub(crate)クレート内限定の公開 を指定するためのアクセス修飾子で、モジュール設計やAPI管理において非常に便利です。本記事では、pub(crate) の基本から応用までを解説します。


1. Rust におけるデフォルトの可視性と pub(crate)

Rust では、アイテムの可視性はデフォルトでプライベート(非公開)です。つまり、修飾子を付けない場合、そのアイテムは定義されたモジュール内でのみアクセス可能になります。

例えば、以下のようなコードは関数がデフォルトでプライベートになります:

fn private_function() {
    println!("This function is private to the module.");
}

一方で、pub(crate) を指定することで、そのアイテムを同じクレート内のどこからでもアクセス可能にできます。これにより、内部実装を保護しつつ、必要な範囲でのみ再利用が可能になります。


基本構文

以下は pub(crate) を適用したアイテムの例です。

関数の場合

pub(crate) fn internal_function() {
    println!("This function is visible only within the same crate.");
}

構造体の場合

pub(crate) struct InternalStruct {
    pub(crate) field: i32, // フィールド単位でも同様に指定可能
}

マクロの場合

macro_rules! example_macro {
    () => {
        println!("This macro is accessible only within the same crate.");
    };
}
pub(crate) use example_macro; // クレート内に公開

2. Rust のアクセス制御とクレート

クレートとは?

クレート(crate)は、Rust プロジェクトのコンパイル単位を指します。以下のような単位で区切られます:

  • バイナリクレート: 実行可能なプログラム(main.rs がエントリーポイント)。
  • ライブラリクレート: 再利用可能なライブラリ(lib.rs がエントリーポイント)。

pub(crate) を適用すると、現在のクレート内であれば、どのモジュールからでもアクセス可能です。しかし、外部クレートからはアクセスできません。


公開範囲の指定方法

Rust のアクセス修飾子には以下の種類があります。それぞれの特徴を理解することで適切な選択が可能になります。

修飾子 公開範囲 説明
デフォルト モジュール内のみ(プライベート) 修飾子を付けない場合のデフォルト設定。
pub 全公開 外部クレートからもアクセス可能
pub(crate) クレート内限定公開 同じクレート内であればどのモジュールからでもアクセス可能
pub(super) 親モジュール限定公開 定義されたモジュールの親からのみアクセス可能
pub(in path) 特定モジュール限定公開(Rust 2018 エディション以上) 指定したモジュール内からのみアクセス可能

3. pub(crate) の実践例

ここでは、pub(crate) を活用してモジュール内のアイテムをクレート全体で共有する例を示します。

ファイル構成

src/
├── main.rs
└── module_a/
    └── macros_a.rs

コード例

macros_a.rs

// マクロを定義
macro_rules! internal_macro {
    () => {
        println!("This macro is only accessible within the current crate.");
    };
}

// クレート内に公開
pub(crate) use internal_macro;

main.rs

mod module_a {
    pub mod macros_a;
}

fn main() {
    // モジュール内のマクロ呼び出し
    module_a::macros_a::internal_macro!(); // OK: 同一クレート内
}

実行結果

This macro is only accessible within the current crate.

4. pub(crate) の活用ポイント

有用なケース

  1. 内部実装の共有
    複数モジュール間で共有する必要があるが、外部クレートには公開したくない場合。

    pub(crate) fn helper_function() {
        println!("This function is shared within the crate.");
    }
    
  2. 外部APIの制限
    必要最小限の公開APIを設計し、内部ロジックを保護。

  3. テストコードとの連携
    #[cfg(test)] モジュール内でテストする際、pub(crate) を使用してアクセス可能にする。


5. 注意点と分かりやすい設計のポイント

注意点

  • 外部公開が必要な場合は不適切
    pub(crate) を指定すると、外部クレートからアクセスできなくなります。外部APIとして公開する必要がある場合は pub を使用してください。

  • 複雑な依存関係に注意
    無闇に pub(crate) を適用すると、モジュール間の依存が複雑化する可能性があります。


設計のポイント

  • 最小限の公開を心がける
    デフォルトがプライベートであることを活かし、本当に必要な範囲にのみ公開修飾子を付ける。

  • モジュール設計を明確にする
    外部クレートが使用する部分(pub)と内部専用の部分(pub(crate))を明確に分ける。


6. まとめ

  • Rustでは、修飾子を付けない場合、デフォルトでプライベート(非公開)。
  • pub(crate) は、クレート内でのみアクセス可能にする修飾子。
  • 内部実装を隠蔽しつつ、必要な範囲で再利用できる設計を可能にする。

Discussion