Object Oriented Programming in Ruby

Roberto Jacquez
8 min readDec 10, 2022

--

“Everything in Ruby is an object,” is the one thing I keep hearing while learning Ruby.

Classes

Classes are in essence, small “factories” that create objects. These objects have built-in methods and attributes. IRB is a tool used to execute Ruby expressions read from the standard input. I am going to start IRB, type a few lines and explain what is happening.

1. "name"
2.=> "name"
3. "name".upcase
4. => "NAME"
5. "name".class
6. => String

Line 1 creates a string of “name”.

Line 2 outputs the string of “name” I just created.

Line 3 shows that “name” has built in methods that can act upon this object in some way. In this case .upcase is the method that capitalizes the string of “name”

Line 4 outputs “NAME” after calling the .upcase method on “name” and hitting enter.

Line 5 Doing .class on a piece of data returns the data type of that piece of data.

Line 6 returns the data type of “name” which is “STRING” in this case.

Aside from being the data type, “STRING” which we saw in line 6, is also the parent class that this instance of a string came from.

Creating A Class and an Instance of That Class

class Student
#some code to describe a student
end

elton = Student.new
elton => #=> #<Student: 0x007fc52c3d9d10>

In Ruby, to create a class I first use the class keyword, hit the space bar and define the class with the first letter capitalized. If I want to create a class that contains two words, the name should be PascalCased. Last, I type “end” to end my class. I created a class called “Student”. The Student class is the blueprints that show how to create individual student objects. These objects contain all the information and behavior of an individual student.

The variable elton points to a new instance of a student. On the Student class, I call the .new method and that will instantiate or create a new instance of a student. Each specific student is called an instance. An instance is a single occurrence of an object produced from the class.

I will create more students:

We now have the elton, mark, and roberto variables pointing at separate instances of the Student class.

So what is #<Student:0x00007f8a0697dc08> ? That is Ruby Object Notation: the way Ruby tells you that you are dealing with an object. #<Student:0x00007f8a0697dc08> is the identifier and this is where the object lives inside memory. The three instances of Student that I created are unique, even though they came from Student.

Instance Methods

To see a list of methods that I can call on the instances of my class, I can call the #methods method on one of the instances:

Wow! All these built-in methods became available to me when I created a class. That’s not the coolest part of it all. The coolest part is that I can create my own. So how does one create an instance method for the Student class? How can I teach the students to raise their hand? I can create an instance method using the def keyword inside of my class:

When I defined #raise_hand within the Student class, raise_hand becomes a #method of all instances of Student. So now all student instances that I create are going to be able to raise their hand.

Where we stand: I can create classes, instances of those classes, and inside of those classes I can create instance methods defining what my instances can do.

Giving a Class Attributes

Generally, when I creates a class, I am going to want to give that class some attributes. I want my Student class to have an attribute of name and an attribute of age. To add these attributes to my class I do:

class Student
attr_accessor :name, :age
end

What I am doing here is saying that all my instances of my Student class will have a name and an age attribute. The method attr_accessor is used when both attr_reader and attr_writer are needed. Both reading and writing data are common in Ruby, so attr_accesor is a useful shortcut. Now that I have added attributes to my class, I can give my three instances of Student a name and an age. I will do it for one of my student instances.

Now I can create as many students as I want and give each student a name and an age. The picture above, however, shows a tedious way of creating new instances of our Student class. What if I want to create 10 students? What about 50? 100? Whew, that’s a lot of typing and in my case, a lot of typos to be made.

There is an easier way.

Initialize

The easier way is to use a special built-in initialization method. I can define it inside my Student class and it is defined like my raise_hand instance method above, except using the initialize keyword. The #initialize method is a method that is called automatically whenever .new is used. If I want each instance of my Student class to be created with certain data, I need to define an #initialize method:

I switched over to Replit.com

Now, whenever I want to create a student, I can give it a name and an age in one line instead of having to type “student1.name= “Elton”” and on a separate line “student1.age=10”. This helps reduce the amount of lines I need to type every time I want to create a new student instance. Amazing.

When I say “@name”, I am referring to the name attribute in my object that I defined in line 2. I am setting the name of the instance of my Student class equal to the name that got passed in in line 9. As is the case with the age. “@name” is an instance variable. Instance variables describe attributes of the instance. Now I can call it throughout the class without having to pass it onto another method as an argument the way you would have to do with a local variable.

Self

I will keep adding to my Student class. Let’s say I want to create a method inside my Student class that will puts a greeting for one of my student objects. That would look something like this:

The self key word refers to the name or the age for the specific object that is calling the greeting method. In this case the object student1 called the greeting method, so it is going to return the name and the age for that specific object. In other words, the self keyword refers to the instance that the #greeting method is being called on. So cool.

Class Variables and Class Methods

Aside from being able to create instance variables and instance methods in Ruby, I am also able to create class variables and class methods. Instance variables hold information regarding an instance and can be identified easily because they have one “@” sign in front of them. In my example above, “@name” and “@age” are instance variables. Instance variables are available in scope for all instance methods in the class. Class variables store values related to a class rather than a particular instance of a class and are also easy to identify because they have two “@” signs in front of them. They are accessible to the entire class. Lets say I want to ask my Student class how many students it has created. I have to start by defining a class variable inside my Student class:

I did so in line 3. I created a class variable student_count. To be able to get a count of all my students, I need to build the capability. I have not given my program the capability to return a student count. Next, I need to create a class method.

Class methods are used to implement behavior related to a class rather than an instance. Instance methods are used to implement behavior related to an instance rather than the whole class. I am going to create a class method to show the syntax:

To create a class method, I use the def key word followed by the self keyword and lastly .name_of_my_class_method. Self refers to the entire class, not an instance of the class. I then added a class method .count which returns the count of students.

To summarize, I have a Student class and inside this class I have a class variable of student_count which I defined in line 3, and a class method of .count (defined in line 5) which returns the count of my students.

Putting it all Together

Now that I know how to create classes, instances of those classes, instance variables, class variables, instance methods, and class methods, I will now be able to add more functionality to my program.

Let’s say that I want to keep track of how many students I am creating. For this I will need a counter that starts at 0. I don’t have any students until i start creating them. For this I will need to create a class variable and set it equal to 0.

I did this in line 3. But wait, I created a new instance of a student, but when I puts “Student.count” I am still getting 0.

To make the counter go up every time I create or initialize an instance of my Student class, I need to add it into my #initialize method:

Voila.

--

--