Seems alright. Only comment I have is that the trailing _ =>
default case is unnecessary (as it’s unreachable, which is by the way also something the compiler will be telling you here).
Furthermore, it is possible to simplify call-sites of the bar
method, in case there’s multiple of those, by implementing the Foo
trait for the enum
, too, e.g.
impl Foo for En {
fn bar(&self) {
match self {
En::A(val) => val.bar(),
En::B(val) => val.bar(),
}
}
}
fn factory(arg: En) {
arg.bar();
}
The answer to this question is yes and no. No, in that there’s no good support for sparing you to write such a long match
for the enum from the language itself. Yes, in that Rust has a quite powerful macro system, so there are crates out there that can write implementations of a trait like the impl Foo for En
above for you automatically. E.g. one such crate is enum_dispatch, which would allow you to write the following:
use enum_dispatch::enum_dispatch;
struct A {}
struct B {}
#[enum_dispatch(En)]
trait Foo {
fn bar(&self);
}
impl Foo for A {
fn bar(&self) {}
}
impl Foo for B {
fn bar(&self) {}
}
// note that the fact that these variants say `A` instead of `A(A)` is just
// a (perhaps slightly weird) convention/abbreviation by the `enum_dispatch` crate
#[enum_dispatch]
enum En {
A,
B,
}
fn factory(arg: En) {
arg.bar();
}
fn main() {
let arg = En::A(A {});
factory(arg);
}
or
use enum_dispatch::enum_dispatch;
struct A {}
struct B {}
#[enum_dispatch]
trait Foo {
fn bar(&self);
}
impl Foo for A {
fn bar(&self) {}
}
impl Foo for B {
fn bar(&self) {}
}
#[enum_dispatch(Foo)]
enum En {
A,
B,
}
fn factory(arg: En) {
arg.bar();
}
fn main() {
let arg = En::A(A {});
factory(arg);
}
Another crate is ambassador which allows you to write
use ambassador::{delegatable_trait, Delegate};
struct A {}
struct B {}
#[delegatable_trait]
trait Foo {
fn bar(&self);
}
impl Foo for A {
fn bar(&self) {}
}
impl Foo for B {
fn bar(&self) {}
}
#[derive(Delegate)]
#[delegate(Foo)]
enum En {
A(A),
B(B),
}
fn factory(arg: En) {
arg.bar();
}
fn main() {
let arg = En::A(A {});
factory(arg);
}