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

笑着哭i 提交于 2019-12-23 18:23:23

问题


Consider the following code in my library:

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

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

The users of my library should be able to use Foo and do_something(), but shall never call helper(). Everything works fine with the code above. But now imagine the code gets huge and I want to separate those definitions into their own files/modules -- they are then pulled back into the root-namespace with pub use. See here:

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;

Now the compiler complains that helper() is private. Indeed it is, but I still want do_something() be able to use it. But I don't want my users to use it. How can I do that?

My attempted solution boils down to "How to access private items of sibling modules?". So answering that question would help me. But providing an alternative solution/a workaround would also be great!


回答1:


As of Rust 1.18, you can use the pub(crate) syntax to expose something throughout your entire crate but not outside of it:

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

All the possibilities, as suggested by the compiler, include:

  • pub(crate): visible only on the current crate
  • pub(super): visible only in the current module's parent
  • pub(in path::to::module): visible only on the specified path



回答2:


Assuming a cargo project with a file structure like this:

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

test.rs is just to demonstrate that it works as intended for users of the library.

In src\lib.rs:

mod foo;

pub use foo::*;

In src\foo\mod.rs:

mod do_something;

pub use self::do_something::*;

pub struct Foo;

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

In src\foo\do_something.rs:

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

In src\bin\test.rs

extern crate mylibname;
use mylibname::*;

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

This compiles for me.



来源:https://stackoverflow.com/questions/36021619/split-implementation-across-multiple-files-modules-and-keep-everything-as-privat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!