跨多个 files/modules 拆分实现并尽可能保持所有内容的私密性

Split implementation across multiple files/modules and keep everything as private as possible

考虑我的库中的以下代码:

pub struct Foo;
impl Foo {
    fn helper(&self) { /* .. */ }
}

pub fn do_something(foo: &Foo) {
    foo.helper();
}

我图书馆的用户应该能够使用 Foodo_something(),但 永远不会 调用 helper()。上面的代码一切正常。但现在假设代码变得庞大,我想将这些定义分离到它们自己的 files/modules 中——然后它们被拉回具有 pub use 的根命名空间。看这里:

mod foo {  // module contents in `src/foo.rs`
    pub struct Foo;
    impl Foo {
        fn helper(&self) { /* .. */ }
    }    
}

mod do_something {  // module contents in `src/do_something.rs`
    use super::Foo;
    pub fn do_something(foo: &Foo) {
        foo.helper();
    }
}

pub use foo::Foo;
pub use do_something::do_something;

现在编译器抱怨说 helper() 是私有的。的确如此,但我还是希望do_something()能够使用它。但我不希望我的用户使用它。我该怎么做?

我尝试的解决方案归结为 "How to access private items of sibling modules?"。所以回答这个问题对我有帮助。但提供替代 solution/a 解决方法也很棒!

假设一个 cargo 项目的文件结构如下:

src\lib.rs
src\foo\mod.rs
src\foo\do_something.rs
src\bin\test.rs

test.rs 只是为了证明它可以按图书馆用户的预期工作。

在src\lib.rs:

mod foo;

pub use foo::*;

在src\foo\mod.rs:

mod do_something;

pub use self::do_something::*;

pub struct Foo;

impl Foo {
    fn helper(&self) { /* .. */ }
}

在src\foo\do_something.rs:

use super::Foo;
pub fn do_something(foo: &Foo) {
    foo.helper();
}

在src\bin\test.rs

extern crate mylibname;
use mylibname::*;

fn main() {
    let foo = Foo;
    do_something(&foo);
    // foo.helper(); //Uncommenting gives an error.
}

这是为我编译的。

Rust 1.18 开始,您可以使用 pub(crate) 语法在整个 crate 中公开某些内容,但不能在 crate 之外公开:

mod foo {  // module contents in `src/foo.rs`
    pub struct Foo;
    impl Foo {
        pub(crate) fn helper(&self) { /* .. */ }
    }    
}

编译器建议的所有可能性包括:

  • pub(crate): 仅在当前 crate 可见
  • pub(super): 仅在当前模块的父级可见
  • pub(in path::to::module): 仅在指定路径可见