ProgrammingRustバックエンド開発者

Rustにおけるモジュールシステム(modules)と可視性(pub、pub(crate)、private)の動作を説明してください。大規模なプロジェクトをどのように整理し、名前の衝突を回避できますか?

Hintsage AIアシスタントで面接を突破

回答

Rustのモジュールシステムは、modキーワードを中心に構築されています。モジュールはコードをファイルや名前空間に論理的に分割することを可能にします。主なポイントは以下の通りです:

  • デフォルトでは、現在のモジュール内ではすべてがプライベート(private)です。
  • pubは要素をすべてのモジュールツリーに対してパブリックにします。
  • pub(crate)はすべてのクレート(ライブラリ/プロジェクト)でアクセス可能です。
  • 名前の衝突は名前空間によって解決されます:明示的なインポート(use mod_name::item)とエイリアスを使用します。

大規模なプロジェクトでは、公開インターフェースをlib.rsまたはmain.rsを通じてのみ説明し、残りはプライベートにするモジュールツリーの使用が推奨されます:

mod network; mod storage; pub use network::api;

ひっかけ問題

構造体がpubとして宣言された場合、他のクレートからアクセス可能になりますか?

回答:いいえ、構造体を単にpubとしてマークするだけでは不十分です。構造体は外部クレートにオープンなモジュールで宣言される必要があり(pub mod)、構造体のフィールドもパブリックでなければ直接アクセスできません。

例:

mod foo { pub struct Bar; } // Barはfooがプライベートであるため、クレートの外では見えません

実際のエラー例


物語

複雑なモジュール構造を持つプロジェクトで、偶然に構造体をpubとして宣言したが、モジュールをpubとしてエクスポートしなかったため、後に別のクレートからその構造体を使用しようとして、型のアクセスできないというエラーが発生した。

物語

大規模なライブラリでは、異なるモジュールが同じ名前をエクスポートしていた(例えば、typesとerrors)。use *を盲目的に使用すると、コンパイル時に名前の衝突が発生した。解決策としてエイリアスを追加し、必要な要素のみをインポートすることになった。

物語

多くの初心者が構造体をpubとして作成しますが、フィールドをprivateのままにしておくため、モジュールの外部での初期化が不可能になります。その結果、別のモジュールからの関数が構造体を直接生成できず、フィールドやコンストラクタをパブリックにしない限りエラーが発生しました。