Walking through "The Java Tutorials" with Rust

Reading 'Object-Oriented Programming Concepts' with Rust in mind

Another weird evening in April 2021

Out of the various lessons in "The Java Tutorials", the most interesting for me to try and follow with Rust is the first lesson of the trail "Learning the Java Language": "Object-Oriented Programming Concepts".

link: Object-Oriented Programming Concepts

My summary of the lesson above

The lesson:

  • Introduces the model of Objects that have state and behavior.

  • Introduces Java classes as "blueprints of objects".

  • Example: After defining a Bicycle Class with some setters and print methods, demonstrating the creation of 2 Bicycle objects, updating their cadence, speed, and gear states, and lastly printing it.

class BicycleDemo {
    public static void main(String[] args) {

        // Create two different 
        // Bicycle objects
        Bicycle bike1 = new Bicycle();
        Bicycle bike2 = new Bicycle();

        // Invoke methods on 
        // those objects
        bike1.changeCadence(50);
        bike1.speedUp(10);
        bike1.changeGear(2);
        bike1.printStates();

        bike2.changeCadence(50);
        bike2.speedUp(10);
        bike2.changeGear(2);
        bike2.changeCadence(40);
        bike2.speedUp(10);
        bike2.changeGear(3);
        bike2.printStates();
    }
}

Trying it with Rust

Well, looks like in Rust this could be directly translated to a Struct that holds the state of an object and an Impl block that defines the behavior of that object:

struct Bicycle {
    cadence : i32,
    speed: i32,
    gear: i32
}

impl Bicycle {
    fn change_cadence(&mut self, cadence : i32) {
        self.cadence = cadence;
    }

    fn speed_up(&mut self, increment : i32) {
        self.speed += increment;
    }

    fn change_gear(&mut self, gear : i32) {
        self.gear = gear;
    }

    fn print_states(&self){
        println!("cadence: {} speed: {} gear: {}", &self.cadence, &self.speed, &self.gear);
    }
}

fn main() {
    let mut bike1 = Bicycle { cadence: 0, speed: 0, gear: 0 };
    let mut bike2 = Bicycle { cadence: 0, speed: 0, gear: 0 };

    bike1.change_cadence(50);
    bike1.speed_up(10);
    bike1.change_gear(2);
    bike1.print_states();

    bike2.change_cadence(50);
    bike2.speed_up(10);
    bike2.change_gear(2);
    bike2.change_cadence(40);
    bike2.speed_up(10);
    bike2.change_gear(3);
    bike2.print_states();

    // prints
    // cadence: 50 speed: 10 gear: 2
    // cadence: 40 speed: 20 gear: 3
}

So far so good :)

Comparing Java and Rust in the example above

Default constructor
  • Rust doesn't have a built-in default constructor like java does.
  • Rust standard library Default Trait defines what happens when default() is called to create a default instance of a Struct.
  • One can use the derive macro to implemented it for a Struct with standard values for primitive types.
  • If I wished a default gear = 1 I'll have to impl the Default trait for Bicycle manually.
Mutability is explicit in Rust
  • To enable the methods change_cadence, speed_up, and change_gear to change the state of a Bicycle, the method signature must contain &mut self (a mutable reference to self). In Java, for comparison, the keyword this is always there unless it's a static method.
  • This is also reflected in the caller site: to enable any state-changing method to be called on the Bicycle instance bike1, we must declare it with the mut keyword.