Suppose I have the following trait in a library:
pub trait Foo {
fn public_op(&self);
fn internal_op(&self);
}
This trait is then implemented for a bunch of structs in this library:
pub struct One {}
impl Foo for One {
fn public_op(&self) {}
fn internal_op(&self) {}
}
pub struct Two {}
impl Foo for Two {
fn public_op(&self) {}
fn internal_op(&self) {}
}
And there is a public function in this library which receives the trait type:
pub fn process(obj: &dyn Foo) {
obj.public_op();
obj.internal_op();
}
The problem is that, since Foo
trait is public in the library, the method internal_op
is also public... but in fact it should have pub(crate)
visibility, because it must be used inside the library only.
As far as I know, all methods of a trait are public, so how can I redesign this problem?
You can split Foo
into two traits, one public and one private.
pub trait Foo: private::Foo {
fn public_op(&self);
}
pub(crate) mod private {
pub trait Foo {
fn internal_op(&self);
}
}
Then implement them both in your library crate as follows:
pub struct One {}
impl Foo for One {
fn public_op(&self) {}
}
impl private::Foo for One {
fn internal_op(&self) {}
}
Then using from outside the library crate would look like:
fn main() {
let one = One {};
one.public_op(); // works
process(&one); // works
//one.internal_op(); // error[E0599]: no method named `internal_op`...
}
This does mean that its impossible for users of your library to implement Foo
as Foo
is now effectively a 'sealed trait'.
See Jack Wrenn's blog post for a discussion of this and alternative approaches.
Rust playground link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With