Using traits to share implementations


#1

Currently we have this (blob reference, master is here) which contains an example of trait use to share implementations.

trait Printable {
    // Default method implementation
    fn print(&self) { println!("{:?}", *self) }
}

impl Printable for int {}

impl Printable for String {
    fn print(&self) { println!("{}", *self) }
}

impl Printable for bool {}

impl Printable for f32 {}

The example defines a trait Printable, which prints things using `"{:?}" so it works on multiple types. AFAIK this is discouraged generally, and one thing that we could use is an example of reuse that doesn’t use type wildcards in a print statement, but ideally something a bit more idiomatic. Can we come up with a better implementation than print wildcards, or perhaps just find a reference implementation where this is useful in practice?

Besides that, there are a few questions to answer with respect to sharing implementation with traits that I’d like to see discussion about.

When is using traits to share implementations a good idea?

Presumably this is useful for part of the reason that inheritance in object-oriented design is useful: you can write the same code once, reuse it many times, and override it if necessary. Anything else?

When is this a bad idea?

A comment in the guidelines suggests discouraging this in a way that is publicly exposed, but this is marked [OPEN] so it could probably use more discussion.

I figure this is related to principles of information hiding: the user of some code shouldn’t have to care about how it’s implemented or whether I change it later to a custom implementation.

With respect to defining “publicly exposed”, I can think of two ways that this could be “public”:

  • The caller/user of your code somehow knows that you used a trait to share the implementation of something.
  • You have declared the trait pub, so the user may use the default implementation themselves.