DEV Community

JustinBass
JustinBass

Posted on

CLASSES, INSTANCES, SETTERS, GETTERS, MARCOS... SAY WHAAA?!

A WALK THROUGH TO REMEMBER


Just when you thought JavaScript and React would throw you for a loop, you thought wrong... Ruby decided to swing by and say "Hey girl, hey!". It's not that Ruby is extremely difficult to take on, it's the idea of having to rewire your mind to tackle a whole new coding language. After all, no one said this would be an easy task.

Image description

I, and I'm sure many coders, can describe the beginning of learning Object Oriented Programming as shown in the example above. One fighting so hard to grasp the concepts of OOP while having to take a few tumbles before allowing ourselves the time and patience to become one with the language. Let's be honest, this language is significantly bigger than ours and has extraordinary pro behaviors. However, we all must start somewhere and the key to starting "somewhere" is truly understanding the fundamentals and terminology in which we one day dream to master.

CLASSES AND INSTANCES IN OBJECT ORIENTED PROGRAMMING


• A class in OOP are models of the program that act as a blueprint for our objects (an instance), the object's attributes, and methods that we can use on our class itself or instances of that class. That's right, there are class methods and instance methods. More on class methods in future lessons! 😉


• An instance in OOP are objects (an instance) of our class that holds detailed data about oneself acquired from attributes that are set with values after a new instance is instantiated.

CLASS VISIUAL


Image description

QUIZ TIME!!!
What is a class in OOP?
A blueprint for our objects(an instance), the object's attributes, and methods that we can use on our class itself or instances of that class.

Before we jump into the visual of an instance it's crucial to know the work a class executes under the hood in order to instantiate an instance of a class. What exactly does it take to instantiate an instance of a class? We know that an instance holds detailed data about oneself acquired from attributes that are set with values after a new instance is instantiated. But how would it be possible for our instance to know about its attributes when instantiated? This is when the extraordinary pro behaviors of OOP take center stage.

CLASS VISIUAL: SETTER AND GETTER INSTANCE METHODS


Image description

•A setter method is an instance method. Using this method allows us to set an attribute with a value of our Person class instance post instantiation. You may be looking at @name and thinking to yourself "Well that looks familiar, it's a variable!". Yes, like JavaScript this is a variable without a var, const, or let but instead begins with an @ attached to the variable name. @name is known as an instance variable.

@name becomes an attribute available to an instance of the Person class. In this case, our instance can have an attribute of name that we can set equal to a 'string' value (or any data type value. In our case a name in real life, would be set to a 'string' data type) after we instantiate a new instance of the Person class. However, a setter method couldn’t be used to its best ability without its side kick...getter method.


Image description

• A getter method is a method of an instance and pairs perfectly with a setter method. Think of the setter method as a writer. Its job is to take in an argument through its parameter, write it to the instance variable @name, and store it away in memory. Let's take a look at what would happen if we instantiate an instance of the Person class without a getter method:

Image description

• Above we have our Person class set with just a setter method that creates an attribute with an instance variable. Now it's time to instantiate an instance of the Person class and set its name attribute equal to a 'string' value:

Image description

• Here we’re saving our new instantiated instance to a local variable called justin. We then take that variable with a value of our new instance and call it on our setter method within our Person class, name=. Remember the setter method has the responsibility to take in an argument through its parameter, write it to the instance variable @name, and store it away in memory. Although we would be able to set the name attribute for our new instance given the setter method "name=", what would happen if we called our instance on justin.name in order to see the name value of the attribute within the instance assigned:

Image description

•As you can see from the example above, we would get an error stating "NoMethodError: undefined method 'name' for #<Person:0x000000011d969bf0 @name="Justin">
Did you mean? name="
. When one sees NoMethodError we should assume as a coder there is no method existing that we can call this instance on. This is why the error is asking us "Did you mean? name=". Keep in mind name= being the setter method, is a completely different call than name being the getter method. Let's bring the getter method back into the equation of our Person class:

Image description

•Now what would happen if we called our new instantiated instance on justin.name_?:

Image description

•As mentioned name= being the setter method, is a completely different call than name being the getter method. This is why a setter method and a getter method go hand and hand. A setter method is a writer. Its job is to take in an argument through its parameter, and _write it to the instance variable @name. A getter method is a _reader. Its job is to read what the setter method saved in memory for us, to the world.

Without both instance methods working together we wouldn't have the full functionality we desire!

SETTER AND GETTER METHODS: MARCOS


It may seem tedious to explicitly code out setter and getter methods within a class every time we'd want to set a new instance with an attribute. Surely, there has to be an easier way to write out both methods. If there is a will, there is most definitely a way. What is another method we could use that essentially is a setter and getter method? Drum roll, please!!! 🥁 MARCOS!!!``

• A marco, is an instance method that implicitly represents our setter and getter methods. Marcos allows the representation of both methods individually or in a lump sum. Are you confused yet? Let's break it down!

MARCOS SETTER AND GETTER METHODS VISUAL: MARCOS REPRESENTING ONE


A marco can represent both a setter and getter individually. Typically it's best to start with a setter method within a class model. Our setter method is what allows us to create an attribute that our instance of the current class can adopt. We'll stick with our name attribute for this instance. Here's an example of a marco representing a setter method implicitly:

Image description

It's important to know and understand a setter method is a writer. Its job is to take in an argument through its parameter, _write it to the instance variable @name, and store it away in memory_. The same exception happens implicitly with marcos. As shown in the example above, the marco syntax for a setter method is "attr_writer :attribute_name". All attribute names within this syntax must begin with a colon. We should now know if calling this method on an instance, the instance will adopt a name attribute when given a value equal to a 'string' datatype:

Image description

Intuitively, we know if we call our instance on justin.name in order to see the name value of the attribute on our instance, we would get an error stating "NoMethodError: undefined method 'name' for #<Person:0x000000011d969bf0 @name="Justin">
Did you mean? name="
:

Image description

QUIZ TIME!!!
Why are we getting the error "NoMethodError: undefined method 'name' for #<Person:0x000000011d969bf0 @name="Justin">
Did you mean? name="
?
There is no method that exists that we can call this instance on!

This tells us we need a marco that implicitly represents a getter method within our Person class:

Image description

The marco syntax for a getter method is similar to the syntax for a setter method with a slight difference. Recall that a getter method acts as a reader. Its job is to _read what the setter method saved in memory for us, to the world._ With that being said, what do you think the marco syntax would be for a getter method? Keep in mind the syntax will always start with attr_. This makes sense seeing that we're setting up an attribute within the Person class for our future instances. If the syntax for a setter method is attr_writer with writer being the key word, what is a key word that describes a getter? READER!:

Image description

Notice we still need to include the name of the attribute beginning with a colon for our implicit getter method provided by marcos. If we think back to the explicit versions of our setter and getter in the Person class, both methods had a representation of the instance variable @name. This is crucial seeing that it helps keep the flow of reading and writing our attributes in sync. Now it's time to put our tag team marcos to the test!:

Image description

If this isn't magic, I don't know what is! We were able to initiate an attribute for our future instances of our Person class given the marco setter method. Even more, we gracefully read the value of the attribute to the world given our marco getter method. Job well done! However as coders, any opportunity given where we can make our code excel in ways we never thought possible, we take it! Although marcos is short-hand for writing explicit setter and getter methods, you would think there's one marco syntax that would implicitly set up both methods for us in lump sum. Bust out your inhalers because you'll be shocked that there is!

MARCOS SETTER AND GETTER METHODS VISUAL: MARCOS REPRESENTING BOTH LUMP SUM


I know what you may be thinking if you're new to the coding world. "WHY IN THE WORLD DID YOU NOT EXPLAIN MARCOS IN THE FIRST PLACE!" I get it. Yes, marcos is an easier set up than explicit setter and getter methods. However, we all must start somewhere and the key to starting "somewhere" is truly understanding the fundamentals and terminology in which we one day dream to master. Without understanding the fundamentals and terminology from which a method truly stems, how do we expect to understand how the "easier" way of doing things actually works? Especially when it's implicit. You know what they say! Slow and steady wins the race.

If you made it this far and truly have a grasp on the concepts of a class, instance, the origin of setter and getter methods, please indulge in our final marco that implicitly represents both a setter and getter lump sum.

Let me introduce to you attr_accessor. The marco attr_accessor allows for a setter and getter method to be grouped into one marco. We no longer need to write two separate marcos, only one marco saving us time:

Image description

Notice with this syntax we still need to apply a colon followed by the attribute name. With our Parent class and marco attr_accessor set up lets instantiate' a new instance of our class saved to the variable, justin`:

Image description

As with our explicit and implicit methods before, our next step would be to take the variable justin with a value of our new instance and call it on our setter method implicitly nested in our marco, name=. This will allow us to officially initialize a name attribute with a "string" value within our the new instance:

Image description

Last but not least it's time to read to the world the value of the name attribute within our new instance! But how? Take the variable justin with a value of our new instance and call it on our getter method implicitly nested in our marco, name:

Image description

THE END OF THE WALK


Image description

We learned the role of a class model and the impact it has in order to instantiate an instance. It also has the ability to to act as a blue print which can hold instance methods that can be called on by an instance of our class. But what if we wanted our instance to have attributes to give the instance a volt packed with detailed data? We would have to imprint setter and getter methods within our class. Because an instance is only an object with an identifier number, it is our job to take advantage of different types of instance methods if we want to set attributes. To do so, we learned how to write explicit setter and getter methods. One method has the responsibility of writing an attribute and the other method has the responsibility of reading the value of the attribute to the world.

With being more than a few ways to write out setter and getter methods, we learned how to take on marcos. A marco is an instance method that implicitly represents our setter and getter methods. Marcos allows the representation of both methods individually or in a lump sum. Both syntax of a marco work under the hood exactly the same. However, writing an attr_accessor is less time consuming than writing attr_writer and attr_reader. Keep in mind the coding world is complexed with strategy and self coding awareness. There will be times using a specific marco syntax will come into play!

Until next time coders! Happy learning and coding! ✌🏽

Resources

1. Ruby Classes and Objects link

2. Ruby Setters and Getters link

3. Ruby Setters and Getters Link Two link

4. attr_accessor, attr_writer and attr_reader link

5. attr_accessor, attr_writer and attr_reader Link Two link

Top comments (0)