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.
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.
• 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
.
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.
•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
.
• 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
:
• 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:
• 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:
•As you can see from the example above, we would get an error stating "NoMethodError: undefined method 'name' for #<Person:0x000000011d969bf0 @name="Justin">
. When one sees
Did you mean? name="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
:
•Now what would happen if we called our new instantiated instance
on justin.name
_?:
•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!
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!
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
:
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:
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="
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
:
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!:
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!:
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!
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:
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`:
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
:
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
:
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)