pub キーワードpub とは何か(一言)
pub は 「このアイテムを現在のモジュールの外からも使えるようにする」 キーワードです。
Rust では デフォルトがすべて非公開(private) です。
pub を書かない限り、関数・構造体・フィールド・型エイリアスはそのモジュール内でしか見えません。
これは Go や Java の「デフォルト公開」とは逆の設計思想で、意図しない API 漏洩を防ぐために選ばれています。
// pub なし → モジュール外からは存在すら見えない
fn internal_helper() { }
// pub あり → モジュール外から呼び出せる
pub fn open_tsm(path: &std::path::Path) -> Result<TsmData, TsmError> { /* ... */ }
Rust の可視性はすべて モジュールツリー を基準に定義されます。
ファイル = モジュールではなく、mod 宣言によるネストが単位です。
// src/lib.rs
pub mod io; // io モジュールを外部に公開
mod internal; // internal モジュールは crate 内のみ
// src/io/mod.rs
pub mod tsm; // tsm サブモジュールを公開
mod shared; // 内部ヘルパー(非公開)
// src/io/tsm.rs
pub fn open(path: &std::path::Path) -> Result<TsmData, TsmError> {
// この関数は io::tsm::open として外部から呼べる
}
pub を付けても、その関数が属する mod 自体が pub でなければ
外部からアクセスできません。可視性はモジュールツリーを通じて「伝播」します。
pub(super)pub(in path)pub(crate)pub| 書き方 | アクセス可能な範囲 | 使いどころ |
|---|---|---|
| (修飾子なし) | 同じモジュール内のみ | 内部実装の隠蔽。デフォルト。積極的に使う |
pub(self) |
同じモジュール内のみ(修飾子なしと同じ) | 明示的に書きたい場合のみ。通常は省略 |
pub(super) |
親モジュールまで | サブモジュール間で共有するが外に漏らしたくない実装 |
pub(in path) |
指定した祖先モジュールまで | サブシステム内で共有するピンポイント公開(使用頻度低) |
pub(crate) |
同一 crate 内のすべてのモジュール | ライブラリ内部 API の標準。外部に漏らしたくないが crate 内で共用する |
pub |
外部 crate を含む全体 | ライブラリの公開 API。意図してユーザに使ってもらう関数・型のみ |
mod outer {
pub fn visible_outside() {} // outer の外から呼べる
fn only_in_outer() {} // outer 内のみ
pub(crate) fn crate_wide() {} // crate 内ならどこでも
mod inner {
pub(super) fn to_outer() {} // outer からは呼べる、crate の他からは不可
fn private() {} // inner 内のみ
}
}
fn main() {
outer::visible_outside(); // OK
outer::crate_wide(); // OK(同一 crate 内)
// outer::only_in_outer(); エラー: private
// outer::inner::to_outer(); エラー: pub(super) は inner の親まで
}
構造体のフィールドは 構造体自体とは独立に可視性を持ちます。 Newtype パターンでよく問題になる「外側 pub / 内側 pub」の違いも同じ仕組みです。
pub struct TsmHeader {
pub frame_count: u32, // 外部から読み書きできる
pub(crate) width: u16, // crate 内でのみ読み書きできる
checksum: u32, // 外部から見えない(内部整合性チェック用)
}
// 外部 crate から:
let h: TsmHeader = tsm_parser::parse(bytes)?;
let n = h.frame_count; // OK: pub
// let w = h.width; エラー: pub(crate)
// let c = h.checksum; エラー: private
pub use による再エクスポート
pub use を使うと、内部の深い場所にある型を、ライブラリのトップレベルに「引き上げて」公開できます。
// src/lib.rs
mod io;
mod domain;
// 内部モジュール構造を隠しつつ、使いやすい API を提供
pub use domain::value_object::TsmData;
pub use io::tsm::open_tsm;
// 使う側: scandata_net::open_tsm(...) と書ける(io::tsm:: を知らなくてよい)
| ステップ | 状況 | 対処 |
|---|---|---|
| 1 | 新しい関数・型を書く | pub なし(private)からスタート |
| 2 | 同じ crate 内の別モジュールから使いたくなった | pub(crate) に昇格。外部に漏れない |
| 3 | テストモジュール(親)から呼びたい内部ヘルパー | pub(super) に昇格。親より上には漏れない |
| 4 | ライブラリのユーザ(外部 crate)に使わせたい | pub に昇格。これが「公開 API」 |
pub にした瞬間から セマンティックバージョニングの対象 になります。
シグネチャを変えると semver major バンプが必要です。
pub(crate) であれば crate 内のリファクタは破壊的変更になりません。
pub の使い方
scandata の Rust 版(ScanDataNet)は Hexagonal Architecture を採用しています。
ドメイン層は副作用ゼロ、fs / io / tokio は Adapter 層に閉じ込める設計です。
この構造と pub の使い方は密接に関係します。
pub か// src/io/tsm.rs(Adapter 層)
pub fn open_tsm(path: &std::path::Path) -> Result<TsmData, TsmError> {
// バイナリ I/O はここだけ。ドメイン層は知らない
}
open_tsm は pub であるべき理由:
main.rs や axum ハンドラ)から呼ばれるpub(crate) から始める// src/domain/value_object.rs
pub(crate) struct FramesData<S> { // まず crate 内公開
pub(crate) data: std::sync::Arc<ndarray::Array3<i16>>,
pub(crate) tag: DataTag,
}
// 外部 API として提供することが決まったら pub に昇格:
// pub struct FramesData<S> { ... }
| レイヤ | モジュール例 | 推奨可視性 | 理由 |
|---|---|---|---|
| ドメイン(純粋関数) | domain::modifier |
pub(crate) |
アプリ内で使うが外部に露出させない |
| I/O Adapter | io::tsm |
pub |
アプリ起動 / テストから直接呼ぶエントリポイント |
| 値オブジェクト(型定義) | domain::value_object |
pub(外部 crate に渡す場合) |
WebSocket の RPC 型として外部に公開 |
| 内部ヘルパー | io::tsm::parse_header |
修飾子なし(private) | 実装詳細。外部に見せる必要なし |
// lib.rs で定義
pub struct TsmHeader {
frame_count: u32, // private フィールド
}
// 外部 crate から構造体リテラルで作ろうとするとエラー
let h = TsmHeader { frame_count: 10 }; // エラー: field is private
// 解決策: コンストラクタ関数を pub で提供する
impl TsmHeader {
pub fn new(frame_count: u32) -> Self {
Self { frame_count }
}
}
mod internal { // pub なし → 外部から見えない
pub fn helper() {} // この pub は無意味(mod が見えないので)
}
// internal::helper() は外部 crate からアクセス不可
pub(crate) は crate 境界を越えない// crate A で定義
pub(crate) fn secret() {}
// crate B(A を依存に持つ)からは呼べない
// a::secret(); エラー: function is pub(crate)
pub use の再エクスポートを忘れる// src/lib.rs で mod だけ宣言して pub use を忘れると
mod io; // io::tsm::open_tsm は外部から直接使えない
// pub use で引き上げる
pub use io::tsm::open_tsm; // これで外部から使えるようになる
pub struct Channel(pub u8) の「外側 pub / 内側 pub」の意味を詳しく解説pub struct FramesData<S> の公開設計例pub fn insert / remove / get の設計pub の実例pub struct TsmData のフィールド公開設計