Overriding methods from Deref

is there a way to override some methods provided by the deref? like this

struct Inner; // this is from another crate
impl Inner {
  fn not_overloaded() {}
  fn overloaded() {
    println!("outer.overloaded() should NOT print this");
  }
}
impl Deref for Outer {
  type Target = Inner;
  fn deref(&self) -> &Self::Target {
    self.inner
  }
}
impl Outer {
  fn overloaded() {
    println!("outer.overloaded() should print this");
  }
}

the use case is something like

impl Outer {
  fn fallible_method(self) -> Result<(), Error)> {
    if self.checks.can_run_fallible_method() {
      self.inner.fallible_method();
    } else {
      return Err(Error::CannotRunFallibleMethod);
    }
  }
}

this safety check wouldnt be possible because self.inner doesnt have the info to know if it'd fail, but not all methods of self.inner require this check so it'd be a boilerplate if i just copied every method it has

No. If you do what you've outlined, method resolution will find Outer's method first. But since you publicly exposed the Inner via the Deref implementation, there's no way to prevent Inner's method from being called (as also shown). In fact, it's not really recommended to try to overload things this way, as you'll likely end up with some situation where deref coercion has unexpectedly kicked in, and Inner's method will be called.

If you want to hide Inner's methods, don't expose the Inner. You will have to wire up the methods manually though, as you said. Macros may help reduce/hide the boilerplate.

Alternatively, have a (perhaps non-public) as_inner(&self) -> &Inner method instead to make things explicit (and perhaps private), and call self.inner().not_overloaded() when you need to.

For more details, you may want to read up on how method resolution is performed.

4 Likes

thank you! should i just name my methods differently, like if the inner has create_user method, mine would be checked_create_user

Depends on the use case I guess -- I can see either way making sense.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.