问题
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 cratepub(super)
: visible only in the current module's parentpub(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