Another option is to create a trait that uses both TraitA
and TraitB
as supertraits and provides a cast to each type:
trait TraitC: TraitA + TraitB {
fn as_trait_a(&self) -> &dyn TraitA;
fn as_trait_b(&self) -> &dyn TraitB;
}
Then have MyType
implement it:
impl TraitC for MyType {
fn as_trait_a(&self) -> &dyn TraitA {
self
}
fn as_trait_b(&self) -> &dyn TraitB {
self
}
}
Once you do that, you can use TraitC
for your Box
and your program logic that uses both TraitA
and TraitB
together.
Sample main to show various ways to use:
fn test_a(a: &TraitA) {
a.say_hello();
}
fn test_b(b: &TraitB) {
b.say_hello();
}
fn main() {
let c: Box<dyn TraitC> = Box::new(MyType {});
TraitA::say_hello(&*c);
TraitB::say_hello(&*c);
c.as_trait_a().say_hello();
c.as_trait_b().say_hello();
test_a(c.as_trait_a());
test_b(c.as_trait_b());
let a: &dyn TraitA = c.as_trait_a();
a.say_hello();
let b: &dyn TraitB = c.as_trait_b();
b.say_hello();
}
Rust Playground
If A
and B
do truly belong together, this better represents that and still gives you the freedom to use them separately if you desire.