I have a trait with optional behavior, and I'm trying to figure out how to use it behind a trait object.

trait Trait { fn required_behavior(&self); fn optional_behavior(&self) where Self: Optional; } trait Optional: Trait {} 

Unfortunately, this trait is not dyn compatible. If I change the bound to Self: Optional + Sized then it is dyn compatible, but the optional_behavior method is understandably non-dispatchable.

If I move the optional method to the subtrait:

trait Trait { fn required_behavior(&self); } trait Optional: Trait { fn optional_behavior(&self); } 

then the trait is dyn compatible, but I need some way to determine whether the Trait is also Optional, and if so downcast a &dyn Trait to a &dyn Optional. OO languages provide a way to downcast, but AFAIK Rust does not.

I could provide a way to access the downcasted subtrait object from the supertrait:

trait Trait { fn required_behavior(&self); fn as_optional(&self) -> Option<&dyn Optional> { None } } trait Optional: Trait { fn optional_behavior(&self); } 

However, this is a bit awkward and feels non-idiomatic. (Iterator doesn't do this for DoubleEndedIterator, so rev() is unusable behind dyn Iterator AFAIK.)

Is there a better way?

6 posts - 4 participants

Read full topic