What are the potential complications to returning a boxed trait object in lieu of Self? Specifically, trait objects are generally forbidden from returning Self, but it looks like this can be worked around at times by returning a trait object instead. For example, the following code defines a trait that can either cache or compute on a piece of data. In order to facilitate a cache and compute in a single line of syntax (obj.set().compute()), I'd like set to return a reference to Self, which is precluded. To get around it, I return a box to a reference of a trait object instead, which appears to work, but I don't fully understand whether this will have unforeseen consequences. Any problem using this kind of pattern?
// Trait that caches and computes
trait MyTrait {
// Set our internal value. Generally, want to return &Self here.
fn set <'a> (&'a mut self, x: f64) -> Box<&'a dyn MyTrait>;
// Compute with our internal value
fn compute(&self, y: f64) -> f64;
}
// Struct that holds internal data that we want to cache
struct MyStruct {
// Internal data
data: f64,
}
// Allows setting and computing on the data
impl MyTrait for MyStruct {
// Set our internal value
fn set <'a> (&'a mut self, x: f64) -> Box<&'a dyn MyTrait> {
self.data = x;
Box::new(self)
}
// Compute with our internal value
fn compute(&self, y: f64) -> f64 {
self.data * 2. * y
}
}
// Function that takes a trait object of MyTrait and then modifies and computes with it
fn foo(obj: &mut dyn MyTrait) {
// Should be 5.52
println!("Result is: {}", obj.set(1.2).compute(2.3));
}
// Test everything
fn main() {
foo(&mut MyStruct { data: 3.4 });
}