DEV Community

Cover image for Polymorphism in Rust and Python. Simple examples
Antonov Mike
Antonov Mike

Posted on • Updated on

Polymorphism in Rust and Python. Simple examples

Disclaimer

The article contains code samples, but not theory and does not pretend to explain the theoretical basis of polymorphism in depth, nor does it explain why and when polymorphism should be used.
The article demonstrates how to implement polymorphism in Rust and Python, but does not explain practical applications of polymorphism in real projects.

Polymorphism

allows you to write code that can work with different types of objects that share some common behavior or interface. For example, you can write a function that can accept any object that can make a sound, such as a dog, a cat, or a bird.

In Rust

one way to achieve polymorphism is to use traits and generics. Traits define a set of methods that a type must implement to satisfy a certain interface. Generics allow you to write code that can work with any type that meets some trait bounds. For example, you can write a function that can accept any type that implements the SoundMaker trait, which defines a method called make_sound. Here is an example of polymorphism in Rust using traits and generics:

// Define a trait that requires a method called make_sound
trait SoundMaker {
    fn make_sound(&self);
}

// Implement the trait for different types
impl SoundMaker for String {
    fn make_sound(&self) {
        println!("{} says hello", self);
    }
}

impl SoundMaker for i32 {
    fn make_sound(&self) {
        println!("{} beeps", self);
    }
}

// Write a generic function that can accept any type that implements the trait
fn make_some_sound<T: SoundMaker>(item: T) {
    item.make_sound();
}

// Call the function with different types
fn main() {
    let name = String::from("Alice");
    let number = 42;
    make_some_sound(name); // Alice says hello
    make_some_sound(number); // 42 beeps
}
Enter fullscreen mode Exit fullscreen mode

In Python

one way to achieve polymorphism is to use duck typing and inheritance. Duck typing is a concept that says that an object's behavior is more important than its type. In other words, if an object can do something, it doesn't matter what type it is. Inheritance is a concept that allows a class to inherit the attributes and methods of another class. For example, you can write a function that can accept any object that has a method called make_sound. Here is an example of polymorphism in Python using duck typing and inheritance:

# A class that has a method called make_sound
class SoundMaker:
    def make_sound(self):
        pass

# A subclasses that inherit from the base  class and override the method
class String(SoundMaker):
    def __init__(self, value):
        self.value = value

    def make_sound(self):
        print(f"{self.value} says hello")

class Integer(SoundMaker):
    def __init__(self, value):
        self.value = value

    def make_sound(self):
        print(f"{self.value} beeps")

# A function that can accept any object that has a method called make_sound
def make_some_sound(item):
    item.make_sound()

# Call the function with different objects
name = String("Alice")
number = Integer(42)
make_some_sound(name)  # Alice says hello
make_some_sound(number)  # 42 beeps
Enter fullscreen mode Exit fullscreen mode

Conclusion

As you can see, the examples are similar in the sense that they both use a common interface (make_sound) to achieve polymorphism. However, they also differ in the syntax and the concepts they use. Rust is more explicit and type-safe, while Python is more dynamic and flexible. Both languages have their own advantages and disadvantages, depending on the use case and the preference of the programmer.

Comparison

Python Classes vs. Rust Traits
Python classes vs Rust structures
Polymorphism in Rust and Python
Abstraction in Rust and Python
Encapsulation in Rust and Python

Top comments (2)

Collapse
 
slobodan4nista profile image
Slobi

Nice topic and post :D

One note, in order to get all the methods of String/Integer in python you would have to subclass it, in rust by implementing trait you are just extending what can be done with original struct.

Hope this helps!

Collapse
 
antonov_mike profile image
Antonov Mike

О! Thank you! I didn't even think of that. Anyway, because of my lack of serious experience in production, every time I think I understand something, I doubt it very much, because all this stuff is very far from how it is applied in real work.