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.
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?
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).
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.