Object Oriented Features Vs Rust

Oct 01, 2021

If you are someone like me, who have coded in Object Oriented Programming Languages before doing Rust like Java, Dart and more. Understing Rust in that context can be frustrating sometimes. In this post, I would like to highlight how Rust goes by when it commes to Object Oriented Design. That will leave you with a mental model on how to translate your usual way of thinking about OOP into your future Rust projects.

Object Oriented Programming consists of four basic principles; encapsulation, abstraction, inheritance and Polymorphism.

Encapsulation

Encapsulation deals with hiding implementation details of objects. So the only way to interact with the object is throught it’s public api. Rust’s methods, structs and enums are private by default though you can make it public by adding pub before them.


pub struct Person{
    // pub keyword allows it to be accessible
	pub name: String,
	// this is private
	age: u32
 }

Inheritance

Inheritance is a mechanism where objects depends on one another without needing to define the safe code again and again. Rust doesn’t have inheritance capability, although you have define structs that depends on other structs’ feals and methods.

pub struct Person {
   name: String,
   age: 12
}

pub struct Child {
  person: Person,
  grade: String
}

Polymorphism

Polymorphism means data that can work with mutliple types. Rust instead uses generics to abstract over different possible types and trait bounds to impose constraints on what those types must provide.

To enable Polymorphism, Rust uses Traits which is a feature that allows a type to have shared fuctionality among different types in Rust.

trait Animal {
    fn walk(&self);
    fn talk(&self);
}

struct Dog {
    name: String,
    num_teeth: u32,
}

impl Animal for Dog {
    fn walk(&self) {
        println!(
            "{} is Barking and is {} years old",
            self.name, self.num_teeth
        )
    }

    fn talk(&self) {
        println!("barks");
    }
}

struct Cat {
    owner: String,
    breed: String,
}

impl Animal for Cat {
    fn walk(&self) {
        println!(
            "{}'s cat is walking and is {} breed",
            self.owner, self.breed
        );
    }
    fn talk(&self) {
        println!("meow");
    }
}

struct Person {
    pub pet: Box<dyn Animal>,
    name: String,
}

fn main() {
    let cat = Cat {
        owner: String::from("veirte"),
        breed: String::from("Havanesse"),
    };

    let dog = Dog {
        name: String::from("Chiu"),
        num_teeth: 12,
    };

    dog.talk();

    let person = Person {
        name: String::from("Yoda"),
        pet: Box::new(cat),
    };

    person.pet.walk();
}