Consider this code that defines a trait RefGen
, a structure Facade
that has a property that can hold a RefGen
and two different new_*
methods that would pick different concrete implementations for the RefGen
.
trait RefGen {
fn gen() -> String;
}
struct FooGen;
impl RefGen for FooGen {
fn gen() -> String {
"foo".to_owned()
}
}
struct BarGen;
impl RefGen for BarGen {
fn gen() -> String {
"bar".to_owned()
}
}
struct Facade<R: RefGen> {
gen: R
}
impl Facade<FooGen> {
fn new_foogen() -> Self {
Facade {
gen: FooGen
}
}
}
impl Facade<BarGen> {
fn new_bargen() -> Self {
Facade {
gen: BarGen
}
}
}
fn main () {}
It works, but it baffles me I would need two impl
blocks for that?
If you want named methods for each type, this is the only way. If you want to do this generically, you can use a generic impl:
This of course requires the
RefGen
trait to offer some kind ofnew
function to create instances:The
where Self: Sized
bound is there so the trait is still object safe. This means that you can create aBox<RefGen>
, but not call thenew
method.Though now you cannot call the
gen
method on yourGenFoo
orGenBar
object, because it's a static method. You need to add a&self
parameter to it. In case you never want to actually create an object of typeGenFoo
orGenBar
, because they will never have fields, you can get rid of thegen
field andnew
constructor entirely by doing all dispatch at compile-time: