Sitemap

OOP between Java and Ruby — part 2

3 min readFeb 24, 2024

--

sending a message vs calling a method

Press enter or click to view image in full size

In this story, I’ll discuss the difference between calling methods in Java and sending message in Ruby.

In Java

In Java, we define classes containing methods and instance variables. When creating objects, the methods we can call are predetermined. Let’s consider the following example:

public class Car {
private Engine engine;
private Wheels wheels;

public Car(Engine engine, Wheels wheels) {
this.engine = engine;
this.wheels = wheels;
}

public Engine getEngine() {
return engine;
}

public void setEngine(Engine engine) {
this.engine = engine;
}

public Wheels getWheels() {
return wheels;
}

public void setWheels(Wheels wheels) {
this.wheels = wheels;
}
}

In this example, we define a Car class, with two instance variables: engine and wheels.

Now, we are pretty sure if we created any object from this car, we’ll always have the same instance variables and the same methods.

Wheels summerWheels = new Wheels();
Car bmwCar = new Car(new Engine(), summerWheels);
Engine engine = bmwCar.getEngine();
bmwCar.getWheels();
Wheels winterWheels = new Wheels();
bmwCar.setWheels(winterWheels);

We have just four methods in this object setEngine, getEngine, setWheels, and getWheels.

what if we created other object from the Car class?

Car teslaCar = new Car(new Engine(), summerWheels);

In Java, each object created from the Car class will have the same four methods: setEngine, getEngine, setWheels, and getWheels. This ensures consistency across instances, and developers can confidently call these methods knowing they are available.

In Ruby

let’s consider the same example in Ruby:

class Car
attr_accessor :engine, :wheels

def initialize(engine, wheels)
@engine = engine
@wheels = wheels
end
end

The class have the same four methods, but in Ruby we can create the getters and setter by adding attr_accessor :engine, :wheels

Get Salah Alawneh’s stories in your inbox

Join Medium for free to get updates from this writer.

let’s create bmw car:

summer_wheels = Wheels.new
bmw_car = Car.new(Engine.new, summer_wheels)
engine = bmw_car.engine
winter_wheels = Wheels.new
bmw_car.wheels = winter_wheels

We had the methods and we can call them as we did in java, lets create the Tesla car in Ruby:

summer_wheels = Wheels.new
tesla_car = Car.new(Engine.new, summer_wheels)

Now, let’s explore the difference. if we want to add autopilot feature specifically for the Tesla car, We can do it as follows:

# Define a getter method for the autopilot feature of the Tesla car
def tesla_car.autopilot
@autopilot
end

# Define a setter method for the autopilot feature of the Tesla car
def tesla_car.autopilot=(autopilot)
@autopilot = autopilot
end

Now that we’ve added the getter and setter methods for the autopilot feature at the object level, specifically for the tesla_car, we can call them as follows:

# Create a new Autopilot object
acc_autopilot = Autopilot.new
# Assign the Autopilot object to the autopilot attribute of the tesla_car object
tesla_car.autopilot = acc_autopilot
# Retrieve and display the type of the autopilot attribute of the tesla_car object
puts "the autopilot type is #{tesla_car.autopilot}"

This example illustrates how objects instantiated from the same class may have different methods.

What about sending message?

As we’ve seen in Ruby, objects that share the same class can have different methods. Now, let’s consider a scenario where we have an array of cars, and our objective is to retrieve all the autopilots from them:

cars = [tesla_car, bmw_car, ferrari_car, kia_car]

Now, if we want to iterate through them:

cars.each { |car| puts car.autopilot}

We’ll have the following exception:

undefined method `autopilot’ for #<Car….

why is that?

because we have some cars don’t have autopilot.., what can we do here?

We can send message:

We send a message to the object because we’re uncertain whether it possesses the desired method or not. Then, we await the response, as shown below:

cars.each do |car|
if car.respond_to?(:autopilot)
car.send(:autopilot)
else
puts "Autopilot method does not exist for this car."
end
end

We first check if the object can respond to our message. If it can, then we’ll send the message using car.send(:autopilot).

Conclusion

In Java, we are certain about the methods we can call on any object, which involves directly calling a method. However, in Ruby, we’re uncertain whether the object has the method, so we send the message, hoping for a response.

Note: If you’re interested in learning more about sending messages in object-oriented programming and its history with Smalltalk, I recommend watching this video: https://www.youtube.com/watch?v=ThewgUBRods

--

--

Salah Alawneh
Salah Alawneh

Written by Salah Alawneh

I'm a Software engineer, passionate about learning, love the journey, spending my free time doing sports