How to have a private part of a trait?











up vote
7
down vote

favorite
1












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.
}
}









share|improve this question
























  • 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, 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















up vote
7
down vote

favorite
1












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.
}
}









share|improve this question
























  • 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, 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













up vote
7
down vote

favorite
1









up vote
7
down vote

favorite
1






1





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.
}
}









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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, 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


















  • 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, 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
















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












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);
}





share|improve this answer























  • @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











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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
































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);
}





share|improve this answer























  • @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















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);
}





share|improve this answer























  • @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













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);
}





share|improve this answer














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);
}






share|improve this answer














share|improve this answer



share|improve this answer








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


















  • @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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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




















































































Popular posts from this blog

Landwehr

Reims

Schenkenzell