I started dabbling into the coding arts a few months ago (hence Code Gazer). I read Chris Pine’s Learn to Program. This is my attempt to elaborate on Pine’s Die Example to further understand the relationships between objects, classes, variables and methods.
Pine Example: Create a die that gives you a random number when you roll it.
1 2 3 4 5 |
|
Everything is an object. Class is an object that allows us to make new classes of objects and defines how those classes behave. A method is the behavior of those objects.
A die is not a basic object in Ruby (i.e. range, integers, strings, arrays and hashes) so in this example, we need to create a new object. We can do that by creating a new class. To create a new class, we use a construct called class
(which defines a class’s behavior) and a class name, Die
. The first letter of a class name is always capitalized.
After creating a class, we need to define its behavior. We can do that by making a method (behavior) that applies to the class Die
: use the word def
followed by the method name, roll
. We define roll
through the logic 1 + rand(6)
which says “return a random number between 1 and 6.”
Simple enough? Let’s go to the next example.
Code Gazer Die Problem 1: Create one die that gives you a random number and color when you roll it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Let’s take it one step at a time. What do we need?
We need a die.
To create an object, we need to create a new class: class Die
.
Each side of the die must have a number and color that correspond with each other.
We need a container (variable) that will hold our numbers and colors. A variable is a storage location containing values. Variables are very useful because we can use them as reference, allowing us to reuse those values at a later time. Here, we need to create a class variable because we want the @@colors
to be available to all methods in the class Die
. Notice the @@
symbol before the word colors? That means colors is a class variable.
Inside the variable, we need slots to hold our numbers and colors. A Hash
is a perfect object for that. A hash variable is like a dictionary: you have a word (the key) and its corresponding definition (the value). Here, we created a Hash
containing a set of colors (values) that correspond to each number in the die (keys). Like this:
1
|
|
When we create the object, die, it needs to roll.
Whenever we make a new object, the initialize method, def initialize
, allows us to set up the object’s initial state: we can provide default values to the attributes of the object (instance variables @num
and @color
). Everything we put in the initialize method (like roll
) becomes a general/default rule and is automatically executed when you create a new object: d = Die.new
.
When we roll the die, we get a random color and number.
The die will roll automatically because it’s being called inside the initialize method, but it doesn’t give us a random color or number yet. We need to create a new method to define the behavior of the Die when it rolls: def roll
.
To see what color and number the die picks, we need to define variables we set up in the initialize method. We use the @
symbol instead of @@
because we want instance variables, not a class variable. Unlike a class variable (which is commonly available to the entire class Die
; this means it’s available for class methods (more on that another time) and instance methods, i.e. roll
), each instance of a class has its own set of instance variables. So here, @num
and @color
applies only to the specific instance created via Die.new
.
We need some logic that allows us to get a random number between 1 – 6 every time the die rolls. We store the number picked in @num
so we can reference back to @@colors
to see which color corresponds with the number. To do that, we set @color
as a key look-up on the @@colors
hash.
1 2 |
|
Did we forget something?
If we create an object, d = Die.new
, the program has access to the random color and number, but the object itself can’t retrieve variables. For example, d.num
and d.color
gives us:
1
|
|
We can see the object has @num=1, @color="yellow"
(Ruby is calling the inspect method on the object, which irb is returning) in it, but we can’t retrieve and use it. To do that, we can use a Ruby construct: attr_accessor
. This construct is a shortcut given to us by the Ruby Gods to help us with our code crafting.
attr_accessor
provides two methods automatically for the developer: a ‘getter’ method and a ‘setter’ method. The sole purpose of the getter is to read/return the value of a particular instance variable. The setter, on the other hand, assigns/sets the value for a particular instance variable. When we write,
1
|
|
we’re telling our program to build these methods behind the scenes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
I think we have everything we need. Let’s run the program and see what we get:
1 2 3 |
|
Awesome. Let’s try it a couple of times to see if it gives us a random color and number.
1 2 3 |
|
It works! Yay!
Phew! I hope I explained those concepts clearly and sufficiently.