I want to take a minute here to show you the usefulness of creating classes in Ruby and how methods inside of our class structure will allow for dynamic objects to be created and modified from that class type. Let’s do it!
Who wants coffee?
As has been stated previously, Classes are a way for us to group specific ‘types‘ of objects together. We group them together in this way because they all likely share similar, if not identical, functionality and purpose to us – both in our programs and in the real world. Case and point: The Cup.
Here we have the beginning phase of our
Cup model. When creating a class, we like to think about what features exist with the object (from the real world) that we are modeling. In this example, we are modeling a Cup and so we have chosen that attributes of this cup include both the
capacity (Max amount of fluid the cup can hold) and
volume (How much fluid is currently in the cup).
We could create a new object from this class right now actually, although it will lack any functionality, nevertheless we can initialize an object and declare the values for capacity and volume as this class exists right now:
But this is boring, we want our Cup class to be dynamic and intuitive. We want it to behave like a real cup in the real world would behave. So let’s add some functionality to our class.
Let’s create a method that mimics something from the real world. Think about it like this. When we initialize a new instance of our Cup object
cup = Cup.new(12, 8) we are saying, based on the arguments from our
def initialize, method part of the class that this new object has a capacity of 12 oz and the current volume is 8 oz. So far so good. How about if we want to drink some of the contents? We gotta method for that.
Here we have created a method called
sip! that takes 1 argument,
amount and then permanently adjusts the value for the total cup volume (which was initially set when we created our
cup object). The convention here is to use the exclamation point to indicate a permanent change of state.
If the def stuff is throwing you off, don’t let it. It’s a simple of defining a method. Def is short for define, that simple. From there, we give this method an argument and then lay the groundwork after that inside of our code block.
So inside of our method we are saying that
@volume is equal to
@volume(current volume – notice the @) –
amount. This is us seeking a way to permanently adjust the total volume of the cup. What if we didn’t do this? We could say that
new_volume = @volume - amount but when we called on our object like this
puts cup.volume,it would still say
8 oz. It would remain unchanged, we want to alter that value.
From there we are now going to create a conditional that says, if we run out of liquid we need to refill it, otherwise we should remind the user that more liquid remains in the cup. This is a good way of visualizing real world object modeling!
So this is great, we are making a lot of progress! We have created a class that represents a Cup from the real world and now have created a method as a way to take away from the contents, but what about adding to the cup once we have taken from it? Enter a new method.
So now, when we call
cup.refill!, it will take the volume of the cup, whatever it is at that point, and refill the volume of the cup to
10 oz, because we don’t want our cup spilling right? But what if it does spill? Well, all of the contents would fall out. How do we represent that in a method? Like so…
We are declaring our variable of
@volume to be
0. This permanently alters the value of that variable and closely resembles a real world scenario where a cup would lose all of its contents when it spills over!
Now, let’s put it all together to show how the whole thing works!
def to_s is just a convenient was of us outputting a string that informs us of the status of the cup, with all of its variables and associated values.
Congratulations, you just created a class from scratch, then an object from scratch that is of that class and then modified your object with methods you created inside of your class structure. Be proud, you are making progress!
Check out these resources for more explanation on creating custom classes in Ruby: