Forgive my "object oriented" mindset (for some value of "object oriented"), but I'm having a hard time figuring out how to create the following analogue in Rust:
In Python, I can define a base class with a method as either abstract/unimplemented ( raise NotImplementedException) or with a default implementation. Then I can create a mixin to override this base behavior. Lastly, I can combine the base class and the mixin into one child class where the mixin method is the method that is bound to the child class. I can do all this in service of trying to fulfill an interface requirement of another piece of code that interfaces with these objects. I want to do this in Rust without using dynamic run-time polymorphism requiring the equivalent of C++ vtables. In Python I would do something like the following with the silly interface do_it:
def do_it(inst):
inst.must_implement_me()
class Base:
def must_implement_me(self):
print('base default implementation')
class Mixin:
def must_implement_me(self):
print('mixin override new default')
class ChildClass(Mixin, Base):
pass
do_it(Base()) # prints "base default implementation"
do_it(ChildClass()) # prints "mixin override new default"
When I try to achieve the same goal in Rust:
trait DoIt {
fn must_implement_me(&self);
}
fn do_it<T: DoIt>(inst: T) {
inst.must_implement_me();
}
trait Base {}
impl<T> DoIt for T where T: Base {
fn must_implement_me(&self) {
println!("base default implementation");
}
}
trait Mixin {}
impl<T> DoIt for T where T: Mixin {
fn must_implement_me(&self) {
println!("mixin override new default");
}
}
struct BaseClass();
impl Base for BaseClass{}
struct ChildClass();
impl Base for ChildClass {}
impl Mixin for BaseClass {}
fn main() {
do_it(BaseClass());
do_it(ChildClass());
}
cargo run complains:
error[E0119]: conflicting implementations of trait `DoIt`:
--> src/main.rs:20:1
|
13 | impl<T> DoIt for T where T: Base {
| -------------------------------- first implementation here
...
20 | impl<T> DoIt for T where T: Mixin + Base {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
Is there a way to tell Rust that the Mixin implementation should win? I understand there is ambiguity, but can I explicitly tell Rust which method implementation wins? If not, how else could this be achieved?