Python-like inheritance

Hi, I am trying to learn rust from a python background and I am struggling with trying to replicate python inheritance in rust. In python i could do

class B(A):
     def __init__(self):
          pass

class A:
     def __init__(self):
          pass
     def something(self):
          print("HI")

B().something()

and B will inherit the functions from A. How do I achieve the same in rust?

Just to clarify the reason why I want this, I want to create 2 struct's, B and C, which that will need to call similar functions, i.e. something. However, I dont want to have to write the function for both structures. So in the python case I would create classes B and C, along with an additional A class which has the function something, and then make B and C inherit A.

For some cases, traits dynamic dispatch could work and combining with Any. Instead of traits, you can also build a composition structure consisting of internal variants.

pub struct A {
    m_variant: AVariant,
}

impl A {
    pub fn x(&self) -> f64 {
        // manual dynamic dispatch
        if let AVariant::B(b) = &self.m_variant {
            return b.x.get();
        }
        0.0
    }
}

enum AVariant {
    B(B),
}

// B(A)
pub struct B {
    pub x: Cell<f64>,
}

You can even use Box inside AVariant to save variants space.

https://users.rust-lang.org/search?q=inheritance

TLDR: generally you're better off using composition rather than trying to emulate inheritance.

class Foo:
    def method(self):
        pass

class Bar:
    def __init__(self):
        self.foo = Foo()

Bar().foo.method()
3 Likes

No. You are trying to learn to write Python in Rust. It just doesn't work, sorry. Mistakes #6a and #6c, basically.

You don't. Try to explain why would you want to do that and there would be, most likely, some way to solve your problem.

But writing Python in Rust, Haskell in Rust or Javascript in Rust… this just doesn't work.

People claim Rust is difficult to learn but that's a lie. Rust is not difficult at all. It's different.

It's not so hard to write programs in Rust. What is hard is to give up the ability to write YourFavoriteLanguage in Rust.

Rust raises the abstraction level. Basically does the same thing structured programming did with code — only with data this time.

And that, ultimately, means you couldn't write Python (or C/C++/Java/Javascript/Perl/PHP/Ruby) in Rust. You can not even write Haskell in Rust because they both raise the abstraction level but Haskell does it by picking immutability while Rust does it by picking single-ownership.

That's why when you think about how certain design pattern may be implemented in Rust the first question you have to ask is: do I even want to implement that in Rust? what “business task” I'm attempting to solve?

Because Rust, quite explicitly, makes certain things impossible and considers it an achievement.

3 Likes

How to approach this depends on why you want it.
One way would be to define a trait with default implementations, and define A and B as implementing it. This will provide A and B with the same behaviour and ability to override it if needed, but it's not exactly the same thing as inheritance, as all will be know at compile time (which performs better that dynamic dispatch).

To get exact same runtime behaviour, you'd need trait objects:
https://doc.rust-lang.org/book/ch17-02-trait-objects.html

Most likely answer is probably "we don't use inheritance here, learn about traits'.

4 Likes

You won't and you don't need to. People coming from OO-languages read Wikipedia and think Rust is an OO-language too, but it's parently not. The truth is that Rust combines low-level things (asm, memory management, etc.), usual C-like things (IP, types, etc.) with higl-level abstrations (IP, FP, traits, generics, etc.). To program in Rust effectively, you must just forget about OOP. Seriously. Structure is not a class, trait is not an interface, method is not an abstract thing, it's just an associated funtion (unless you use trait dynamic dispatch). It's even better to learn Rust after Fortran than after Python, because Fortran programmers are usually ready to learn and improve, while OO langs programmers think they're on top of the world. I apologize if i offended someone, that wasn't the target. I just wanted to show the correct way of doing this. And i'll do it.

fn something() {
    println!("HI");
}

Yes. It's just a function. You don't need a custom type for solving the problem. Creating a structure and a trait would just make your code less readable and in some cases slower (usually zero-cost tho).

If you really need this kind of abstractions tho (here you don't), use traits and custom types.

Thanks for your attention.

5 Likes