Can the implant be split into different modules?
I am trying to split impl
into different modules. Items in child blocks impl
must be accessible to the parent impl
, but not publicly accessible by users of the implemented structure / enumeration.
Here's my attempt:
mod foo {
pub struct Foo {
field: String
}
impl Foo {
pub fn new() -> Foo {
Foo { field: "Joe".to_string() }
}
pub fn pubfn(&self) {
self.my_impl();
}
}
// Ideally, this should be in a separate file
mod foo_impl_details {
impl super::Foo {
// If I make this `pub`, it will be publicly visible to
// users of `Foo`, not just the impl block in `super`
fn my_impl(&self) {
println!("{} reporting for duty!", self.field);
}
}
}
}
fn main() {
let foo = foo::Foo::new();
foo.pubfn();
}
This results in a compilation error:
<anon>:11:13: 11:27 error: method `my_impl` is private
<anon>:11 self.my_impl();
^~~~~~~~~~~~~~
If I mark the my_impl
method pub
, it will be public not only to the parent module impl
, but also to external users foo::Foo
, which I don't want.
source to share
This is similar to expected behavior: a method my_impl
is private and therefore only visible within the module in which it is declared. On the other hand, it is weird that the version pub
is visible all over the place, despite being foo_impl_details
a private module. I wrote # 16398 about this.
You can decouple modules (and therefore files, since it is the mod foo { ... }
same as mod foo;
code in foo.rs
or foo/mod.rs
) while maintaining privacy by using standalone functions like
mod foo {
pub struct Foo {
field: String
}
impl Foo {
pub fn new() -> Foo {
Foo { field: "Joe".to_string() }
}
pub fn pubfn(&self) {
foo_impl_details::my_impl(self);
}
}
mod foo_impl_details {
fn my_impl(x: &super::Foo) {
println!("{} reporting for duty!", x.field);
}
}
}
There is no difference between independent functions and methods other than the call syntax.
Also, there are a lot of problems with writing non-trait impls not contiguous with the type declaration, so this behavior is probably not by design, for example.
And thus an RFC to (temporarily) remove this feature.
source to share
It works.
mod foo {
use self::extension::Extension;
pub struct Foo {
field: String
}
impl Foo {
pub fn new() -> Foo {
Foo { field: "Joe".to_string() }
}
pub fn pubfn(&self) {
self.my_impl();
}
}
mod extension {
pub trait Extension {
fn my_impl(&self);
}
impl Extension for super::Foo {
fn my_impl(&self) {
println!("{} reporting for duty!", self.field);
}
}
}
}
source to share
Regular impl
blocks? Well, this is something that is currently quite awkward, and while you can work around these errors a little, it can be removed . I highly recommend not trying this in the first place.
As for the implementations of the trait, they can go anywhere in the box.
source to share