How to have a private part of a trait?
up vote
7
down vote
favorite
In a crate I write, I have a bunch of internal structs public to the user and that share some code. Some of the shared code is public, some is an internal implementation. To share efficiently the code, I am using macros, but now that the project has more features, this begins to be messy, and I am not satisfied by the semantic of this.
I would like to use a trait, but without exposing the implementation. For example:
pub trait MyTrait {
type Next;
// This function is for the user.
fn forward(&self) -> Self::Next {
self.do_the_job()
}
// This function is for the user.
fn stop(&self) {
self.do_the_job();
}
// This function is an implementation detail.
fn do_the_job(&self) -> Self::Next;
}
I want the user to see and use forward and stop, but not do_the_job, while my data would only implement do_the_job.
Is it possible to design my code to do something like that? I have tried to imagine some solutions, but nothing has come to my mind.
Playground
In an object oriented language with inheritance, I would do (pseudo code):
public interface MyTrait {
type Next;
fn forward(&self) -> Self::Next;
fn stop(&self);
}
public abstract class MyCommonCode extends MyTrait {
fn forward(&self) -> Self::Next {
self.do_the_job()
}
fn stop(&self) {
self.do_the_job();
}
protected abstract fn do_the_job(&self) -> Self::Next;
}
public MyType extends MyCommonCode {
type Next = i32;
protected override fn do_the_job(&self) -> Self::Next {
// etc.
}
}
design-patterns rust traits
|
show 14 more comments
up vote
7
down vote
favorite
In a crate I write, I have a bunch of internal structs public to the user and that share some code. Some of the shared code is public, some is an internal implementation. To share efficiently the code, I am using macros, but now that the project has more features, this begins to be messy, and I am not satisfied by the semantic of this.
I would like to use a trait, but without exposing the implementation. For example:
pub trait MyTrait {
type Next;
// This function is for the user.
fn forward(&self) -> Self::Next {
self.do_the_job()
}
// This function is for the user.
fn stop(&self) {
self.do_the_job();
}
// This function is an implementation detail.
fn do_the_job(&self) -> Self::Next;
}
I want the user to see and use forward and stop, but not do_the_job, while my data would only implement do_the_job.
Is it possible to design my code to do something like that? I have tried to imagine some solutions, but nothing has come to my mind.
Playground
In an object oriented language with inheritance, I would do (pseudo code):
public interface MyTrait {
type Next;
fn forward(&self) -> Self::Next;
fn stop(&self);
}
public abstract class MyCommonCode extends MyTrait {
fn forward(&self) -> Self::Next {
self.do_the_job()
}
fn stop(&self) {
self.do_the_job();
}
protected abstract fn do_the_job(&self) -> Self::Next;
}
public MyType extends MyCommonCode {
type Next = i32;
protected override fn do_the_job(&self) -> Self::Next {
// etc.
}
}
design-patterns rust traits
You can put the private function in a private trait, and make the public trait depend on it.
– Sven Marnach
Nov 8 at 8:59
@SvenMarnach I don't think that it will work in this context. I tried a few different solutions, but cannot satisfy the compiler. Do you have a POC?
– hellow
Nov 8 at 9:10
@SvenMarnach This is forbidden:private trait in public interface.
– Boiethios
Nov 8 at 9:24
1
@Boiethios Here's an example on the playground without the associated type.
– Sven Marnach
Nov 8 at 9:26
1
Yep,byteorderdoes that as well docs.rs/byteorder/1.2.7/src/byteorder/lib.rs.html#166 to protect others from implementing their trait
– hellow
Nov 8 at 9:40
|
show 14 more comments
up vote
7
down vote
favorite
up vote
7
down vote
favorite
In a crate I write, I have a bunch of internal structs public to the user and that share some code. Some of the shared code is public, some is an internal implementation. To share efficiently the code, I am using macros, but now that the project has more features, this begins to be messy, and I am not satisfied by the semantic of this.
I would like to use a trait, but without exposing the implementation. For example:
pub trait MyTrait {
type Next;
// This function is for the user.
fn forward(&self) -> Self::Next {
self.do_the_job()
}
// This function is for the user.
fn stop(&self) {
self.do_the_job();
}
// This function is an implementation detail.
fn do_the_job(&self) -> Self::Next;
}
I want the user to see and use forward and stop, but not do_the_job, while my data would only implement do_the_job.
Is it possible to design my code to do something like that? I have tried to imagine some solutions, but nothing has come to my mind.
Playground
In an object oriented language with inheritance, I would do (pseudo code):
public interface MyTrait {
type Next;
fn forward(&self) -> Self::Next;
fn stop(&self);
}
public abstract class MyCommonCode extends MyTrait {
fn forward(&self) -> Self::Next {
self.do_the_job()
}
fn stop(&self) {
self.do_the_job();
}
protected abstract fn do_the_job(&self) -> Self::Next;
}
public MyType extends MyCommonCode {
type Next = i32;
protected override fn do_the_job(&self) -> Self::Next {
// etc.
}
}
design-patterns rust traits
In a crate I write, I have a bunch of internal structs public to the user and that share some code. Some of the shared code is public, some is an internal implementation. To share efficiently the code, I am using macros, but now that the project has more features, this begins to be messy, and I am not satisfied by the semantic of this.
I would like to use a trait, but without exposing the implementation. For example:
pub trait MyTrait {
type Next;
// This function is for the user.
fn forward(&self) -> Self::Next {
self.do_the_job()
}
// This function is for the user.
fn stop(&self) {
self.do_the_job();
}
// This function is an implementation detail.
fn do_the_job(&self) -> Self::Next;
}
I want the user to see and use forward and stop, but not do_the_job, while my data would only implement do_the_job.
Is it possible to design my code to do something like that? I have tried to imagine some solutions, but nothing has come to my mind.
Playground
In an object oriented language with inheritance, I would do (pseudo code):
public interface MyTrait {
type Next;
fn forward(&self) -> Self::Next;
fn stop(&self);
}
public abstract class MyCommonCode extends MyTrait {
fn forward(&self) -> Self::Next {
self.do_the_job()
}
fn stop(&self) {
self.do_the_job();
}
protected abstract fn do_the_job(&self) -> Self::Next;
}
public MyType extends MyCommonCode {
type Next = i32;
protected override fn do_the_job(&self) -> Self::Next {
// etc.
}
}
design-patterns rust traits
design-patterns rust traits
edited Nov 9 at 10:28
asked Nov 8 at 8:56
Boiethios
9,58243269
9,58243269
You can put the private function in a private trait, and make the public trait depend on it.
– Sven Marnach
Nov 8 at 8:59
@SvenMarnach I don't think that it will work in this context. I tried a few different solutions, but cannot satisfy the compiler. Do you have a POC?
– hellow
Nov 8 at 9:10
@SvenMarnach This is forbidden:private trait in public interface.
– Boiethios
Nov 8 at 9:24
1
@Boiethios Here's an example on the playground without the associated type.
– Sven Marnach
Nov 8 at 9:26
1
Yep,byteorderdoes that as well docs.rs/byteorder/1.2.7/src/byteorder/lib.rs.html#166 to protect others from implementing their trait
– hellow
Nov 8 at 9:40
|
show 14 more comments
You can put the private function in a private trait, and make the public trait depend on it.
– Sven Marnach
Nov 8 at 8:59
@SvenMarnach I don't think that it will work in this context. I tried a few different solutions, but cannot satisfy the compiler. Do you have a POC?
– hellow
Nov 8 at 9:10
@SvenMarnach This is forbidden:private trait in public interface.
– Boiethios
Nov 8 at 9:24
1
@Boiethios Here's an example on the playground without the associated type.
– Sven Marnach
Nov 8 at 9:26
1
Yep,byteorderdoes that as well docs.rs/byteorder/1.2.7/src/byteorder/lib.rs.html#166 to protect others from implementing their trait
– hellow
Nov 8 at 9:40
You can put the private function in a private trait, and make the public trait depend on it.
– Sven Marnach
Nov 8 at 8:59
You can put the private function in a private trait, and make the public trait depend on it.
– Sven Marnach
Nov 8 at 8:59
@SvenMarnach I don't think that it will work in this context. I tried a few different solutions, but cannot satisfy the compiler. Do you have a POC?
– hellow
Nov 8 at 9:10
@SvenMarnach I don't think that it will work in this context. I tried a few different solutions, but cannot satisfy the compiler. Do you have a POC?
– hellow
Nov 8 at 9:10
@SvenMarnach This is forbidden:
private trait in public interface.– Boiethios
Nov 8 at 9:24
@SvenMarnach This is forbidden:
private trait in public interface.– Boiethios
Nov 8 at 9:24
1
1
@Boiethios Here's an example on the playground without the associated type.
– Sven Marnach
Nov 8 at 9:26
@Boiethios Here's an example on the playground without the associated type.
– Sven Marnach
Nov 8 at 9:26
1
1
Yep,
byteorder does that as well docs.rs/byteorder/1.2.7/src/byteorder/lib.rs.html#166 to protect others from implementing their trait– hellow
Nov 8 at 9:40
Yep,
byteorder does that as well docs.rs/byteorder/1.2.7/src/byteorder/lib.rs.html#166 to protect others from implementing their trait– hellow
Nov 8 at 9:40
|
show 14 more comments
1 Answer
1
active
oldest
votes
up vote
3
down vote
Traits are similar to interfaces:
Traits are Rust’s sole notion of interface.
An interface is meant to document available methods, to have an interface with private methods makes no sense. Correspondingly, in Rust you can't have different levels of visibility in one trait. If you can see the trait, you can always see all of it. However, Rust traits are subtly different from interfaces: they combine declarations and implementations. I see how it would be intuitive to have a trait with some private functions.
For some time it was possible to split a trait into a public and private part. You would have two traits, one containing your public interface, the other with your private functionality, but this is being removed in newer versions of Rust.
The current workaround is still splitting the trait, but the private part must now be represented by a public trait within a private module. To explain this, here is some sample code:
// this module contains a public trait Inc, to increment a value
// and it implements it by using a private trait Add
mod my_math {
pub struct Val {
pub val: i32,
}
// this is necessary to encapsulate the private trait
// the module is private, so the trait is not exported
mod private_parts {
pub trait Add {
fn add(&mut self, i32);
}
}
// in the following code, we have to use adequate namespacing
impl private_parts::Add for Val {
fn add(&mut self, other: i32) {
self.val += other;
}
}
pub trait Inc: private_parts::Add {
fn inc(&mut self);
}
impl Inc for Val {
fn inc(&mut self) {
use my_math::private_parts::Add;
self.add(1)
}
}
}
fn main() {
use my_math::Inc;
let mut b = my_math::Val { val: 3 };
println!("value: {}", b.val);
b.inc();
println!("value: {}", b.val);
}
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
2
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
Traits are similar to interfaces:
Traits are Rust’s sole notion of interface.
An interface is meant to document available methods, to have an interface with private methods makes no sense. Correspondingly, in Rust you can't have different levels of visibility in one trait. If you can see the trait, you can always see all of it. However, Rust traits are subtly different from interfaces: they combine declarations and implementations. I see how it would be intuitive to have a trait with some private functions.
For some time it was possible to split a trait into a public and private part. You would have two traits, one containing your public interface, the other with your private functionality, but this is being removed in newer versions of Rust.
The current workaround is still splitting the trait, but the private part must now be represented by a public trait within a private module. To explain this, here is some sample code:
// this module contains a public trait Inc, to increment a value
// and it implements it by using a private trait Add
mod my_math {
pub struct Val {
pub val: i32,
}
// this is necessary to encapsulate the private trait
// the module is private, so the trait is not exported
mod private_parts {
pub trait Add {
fn add(&mut self, i32);
}
}
// in the following code, we have to use adequate namespacing
impl private_parts::Add for Val {
fn add(&mut self, other: i32) {
self.val += other;
}
}
pub trait Inc: private_parts::Add {
fn inc(&mut self);
}
impl Inc for Val {
fn inc(&mut self) {
use my_math::private_parts::Add;
self.add(1)
}
}
}
fn main() {
use my_math::Inc;
let mut b = my_math::Val { val: 3 };
println!("value: {}", b.val);
b.inc();
println!("value: {}", b.val);
}
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
2
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
add a comment |
up vote
3
down vote
Traits are similar to interfaces:
Traits are Rust’s sole notion of interface.
An interface is meant to document available methods, to have an interface with private methods makes no sense. Correspondingly, in Rust you can't have different levels of visibility in one trait. If you can see the trait, you can always see all of it. However, Rust traits are subtly different from interfaces: they combine declarations and implementations. I see how it would be intuitive to have a trait with some private functions.
For some time it was possible to split a trait into a public and private part. You would have two traits, one containing your public interface, the other with your private functionality, but this is being removed in newer versions of Rust.
The current workaround is still splitting the trait, but the private part must now be represented by a public trait within a private module. To explain this, here is some sample code:
// this module contains a public trait Inc, to increment a value
// and it implements it by using a private trait Add
mod my_math {
pub struct Val {
pub val: i32,
}
// this is necessary to encapsulate the private trait
// the module is private, so the trait is not exported
mod private_parts {
pub trait Add {
fn add(&mut self, i32);
}
}
// in the following code, we have to use adequate namespacing
impl private_parts::Add for Val {
fn add(&mut self, other: i32) {
self.val += other;
}
}
pub trait Inc: private_parts::Add {
fn inc(&mut self);
}
impl Inc for Val {
fn inc(&mut self) {
use my_math::private_parts::Add;
self.add(1)
}
}
}
fn main() {
use my_math::Inc;
let mut b = my_math::Val { val: 3 };
println!("value: {}", b.val);
b.inc();
println!("value: {}", b.val);
}
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
2
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
add a comment |
up vote
3
down vote
up vote
3
down vote
Traits are similar to interfaces:
Traits are Rust’s sole notion of interface.
An interface is meant to document available methods, to have an interface with private methods makes no sense. Correspondingly, in Rust you can't have different levels of visibility in one trait. If you can see the trait, you can always see all of it. However, Rust traits are subtly different from interfaces: they combine declarations and implementations. I see how it would be intuitive to have a trait with some private functions.
For some time it was possible to split a trait into a public and private part. You would have two traits, one containing your public interface, the other with your private functionality, but this is being removed in newer versions of Rust.
The current workaround is still splitting the trait, but the private part must now be represented by a public trait within a private module. To explain this, here is some sample code:
// this module contains a public trait Inc, to increment a value
// and it implements it by using a private trait Add
mod my_math {
pub struct Val {
pub val: i32,
}
// this is necessary to encapsulate the private trait
// the module is private, so the trait is not exported
mod private_parts {
pub trait Add {
fn add(&mut self, i32);
}
}
// in the following code, we have to use adequate namespacing
impl private_parts::Add for Val {
fn add(&mut self, other: i32) {
self.val += other;
}
}
pub trait Inc: private_parts::Add {
fn inc(&mut self);
}
impl Inc for Val {
fn inc(&mut self) {
use my_math::private_parts::Add;
self.add(1)
}
}
}
fn main() {
use my_math::Inc;
let mut b = my_math::Val { val: 3 };
println!("value: {}", b.val);
b.inc();
println!("value: {}", b.val);
}
Traits are similar to interfaces:
Traits are Rust’s sole notion of interface.
An interface is meant to document available methods, to have an interface with private methods makes no sense. Correspondingly, in Rust you can't have different levels of visibility in one trait. If you can see the trait, you can always see all of it. However, Rust traits are subtly different from interfaces: they combine declarations and implementations. I see how it would be intuitive to have a trait with some private functions.
For some time it was possible to split a trait into a public and private part. You would have two traits, one containing your public interface, the other with your private functionality, but this is being removed in newer versions of Rust.
The current workaround is still splitting the trait, but the private part must now be represented by a public trait within a private module. To explain this, here is some sample code:
// this module contains a public trait Inc, to increment a value
// and it implements it by using a private trait Add
mod my_math {
pub struct Val {
pub val: i32,
}
// this is necessary to encapsulate the private trait
// the module is private, so the trait is not exported
mod private_parts {
pub trait Add {
fn add(&mut self, i32);
}
}
// in the following code, we have to use adequate namespacing
impl private_parts::Add for Val {
fn add(&mut self, other: i32) {
self.val += other;
}
}
pub trait Inc: private_parts::Add {
fn inc(&mut self);
}
impl Inc for Val {
fn inc(&mut self) {
use my_math::private_parts::Add;
self.add(1)
}
}
}
fn main() {
use my_math::Inc;
let mut b = my_math::Val { val: 3 };
println!("value: {}", b.val);
b.inc();
println!("value: {}", b.val);
}
edited Nov 8 at 14:02
Shepmaster
142k11265398
142k11265398
answered Nov 8 at 12:29
lhk
6,18385387
6,18385387
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
2
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
add a comment |
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
2
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
@hellow thanks for doing it for me :)
– lhk
Nov 8 at 12:44
2
2
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
I've read up a bit on this, and it looks like making a public trait dependent on a private trait won't become an error in the future. See allso RFC 2145 for the new proposed rules.
– Sven Marnach
Nov 8 at 13:08
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53204327%2fhow-to-have-a-private-part-of-a-trait%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
You can put the private function in a private trait, and make the public trait depend on it.
– Sven Marnach
Nov 8 at 8:59
@SvenMarnach I don't think that it will work in this context. I tried a few different solutions, but cannot satisfy the compiler. Do you have a POC?
– hellow
Nov 8 at 9:10
@SvenMarnach This is forbidden:
private trait in public interface.– Boiethios
Nov 8 at 9:24
1
@Boiethios Here's an example on the playground without the associated type.
– Sven Marnach
Nov 8 at 9:26
1
Yep,
byteorderdoes that as well docs.rs/byteorder/1.2.7/src/byteorder/lib.rs.html#166 to protect others from implementing their trait– hellow
Nov 8 at 9:40