I just watched an old video of ThePrimeagen about message passing in OOP, and I wanted to write an article that explained the topic better. So here we are.
Message passing, for those who don't know, is essentially a trigger for an object to act. Somehow, "message passing" became "method calls". Javascript, despite not being Smalltalk, already has a nice mechanism for messages, though. You can access an object's fields dynamically:
obj['message'](...params);
This allows you to access the behavior associated with the message. Behavior is not the same as a method call. Behaviors can be many private methods at once, public methods or even reference usage of other objects. What matters is the declarative API that message passing enables. This attains the principle of Abstraction
.
const jose = new Person('José');
jose['greet'](); // prints "Hello, I am José!"
jose['sum'](2, 2); // prints "I am bad at math!!!"
If we give the same message to different objects, what happens? We get Polymorphism
.
const jose = new Person('José');
const fusca = new Car('Fusca');
const pimenta = new Dog('Pimenta');
jose['greet'](); // prints "Hello, I am José!"
fusca['greet'](); // prints "Beep!"
pimenta['greet'](); // prints "Woof!"
To teach José some math, we can't simply open José's brain and shove math inside it — it isn't how brains work in real life, so it won't be how we model our system here. José will be properly taught. Let's introduce him to Maria, a teacher:
const jose = new Person('José');
const maria = new Teacher('Maria'); // Note the new class
maria['greet'](jose); // prints "Hello, José, I am Maria!"
jose['greet-back'](maria); // prints "Hello, Maria, nice to meet you!"
// José even knows how to `greet-back` — how fancy.
See how the greet
message is different this time? Behaviors can be modified with parameters. This is also a great example of the principle of Inheritance
: A teacher is a person, and all persons know how to greet. Maria, being a teacher and person, knows how to greet too.
Finally, let's teach José some math:
// Checking again if José knows math:
jose['sum'](2, 2); // prints "I am bad at math!!!" still!
// Nothing new. Let's have Maria to teach him:
maria['teach'](jose, 'math');
jose['sum'](2, 2); // prints "2 plus 2 is 4."
What happened with José? Did Maria just shove math into his brain? Let's take a look at the teach
behavior below. Since objects cannot change the state of other objects, you must pass the message and let them deal with it.
class Teacher extends Person {
// ... other logic goes here
teach(person, subject) {
person['learn'](subject);
}
}
That rule of not touching the internal state of another object is called Encapsulation
. Only José can truly learn — Maria can only help. José is a good student and, now that he knows math, he behaves differently when prompted to sum two numbers.
And there you have it: We explored the four pillars of Object Oriented Programming through the lenses of Message Passing.
Hope you enjoyed it!
Top comments (0)