Automatically implement functions of member variable for struct

Considering the following example, I would like to auto-implement all functions of Sub for Wrapper, no matter how many functions Sub has.

This would both hide the internals of Wrapper (which may be important in some cases), and makes the code shorter since one doesn't need to fetch the member variable before calling the function (e.g. wrapper.sub.function() or wrapper.sub().function()

struct Sub {
    name: String
}

impl Sub {
    pub fn function(&self) {
        println!("Hello World, I'm {}", self.name)
    }
}

struct Wrapper {
    sub: Sub,
}

impl Wrapper {
    pub fn new() -> Self {
        Wrapper { sub: Sub { name: "a ghost".to_string() } }
    }
}

I'm looking for something that would implement functions of the following pattern for Wrapper:

    pub fn function(&self) {
        self.sub.function()
    }

Is that currently possible in Rust? Using derive/macros would be fine by me if that would solve the issue. I get there may be issues when Sub implements a function whose name is already defined in Wrapper, but I could work around that easily.

You can (ab)use Deref, but this is considered an anti-pattern:

use core::ops::Deref;

struct Sub {
    name: String
}

impl Sub {
    pub fn function(&self) {
        println!("Hello World, I'm {}", self.name)
    }
}

struct Wrapper {
    sub: Sub,
}

impl Wrapper {
    pub fn new() -> Self {
        Wrapper { sub: Sub { name: "a ghost".to_string() } }
    }
}
impl Deref for Wrapper {
    type Target = Sub;

    fn deref(&self) -> &Self::Target {
        &self.sub
    }
}

fn main() {
    let wrapper = Wrapper::new();
    
    wrapper.function();
}

Thanks for the answer, I also feel like this is no pretty solution, but it may be just what I'm looking for. I'll see whether it makes sense in my code :slight_smile:

You haven't said what you are trying to use this for, but it sounds like you have previously used an Object-Oriented language and are wanting to do inheritance in Rust.

If so, it's probably not going to work out for you because Rust doesn't allow inheritance. Deref coersion is one way to "fake it", but this isn't an equivalent of inheritance and was never intended to be, so you'll start to see the cracks forming pretty quickly.

See mistake Mistake 6a: Try to make Rust Look OOP:

When you don't know where to start, it may be tempting to build a hierarchical class tree. You may want to say that cars are obviously vehicles and that trucks are kind of cars, or the reverse maybe.

Just don't. Don't look for tricks to simulate inheritance. Rust isn't designed this way and it doesn't help to try to make it OOP. It will most notably lead you to ownership problems as OOP designs usually require keeping many references to various parts of the data.

If that's what you were going for, you might want to take a step back and try a different approach.

1 Like

I think you may be right with this, at least with the point that I have indeed used OOP before switching to rust.

What I ended up doing was implenting the functions I had in Sub and wanted Wrapper to expose directly in Wrapper - and it even made sense doing so, it's not a dirty patch.

So for anyone in the future reading this: Michael might be right, try to look at your problem from a different angle :wink: