Launch Your Understanding From 0-60 with Ruby Classes
Just as with any object-oriented programming language, class is an important part of Ruby. Everything in Ruby revolves around objects, and all of these objects belong to a class
. Unlike in other languages, where each object can have multiple classes, objects in Ruby can only belong to one class. A class
is a structure containing similar properties that each instance
in the class share, but each instance
can have different characteristics for those properties. Arrays, Hashes, and Strings are all examples of classes!
I threw out a lot of terminology, so let me show you an example:
class SuperCar def initialize(make, model, year, horsepower, torque) @make = make @model = model @year = year @hp = horsepower @tq = torque end def print_specs puts "This #{@year} #{@make} #{@model} has #{@hp} horsepower and #{@tq} lb-ft of torque." end end car_1 = SuperCar.new('Ferrari','458 Italia',2013,570,398) car_2 = SuperCar.new('Lamborghini','Aventador',2012,691,508) car_3 = SuperCar.new('McLaren','MP4-12C',2014,616,443)
There are several pieces of code to look at here. We have a class called SuperCar
and three instances called car_1, car_2, and car_3. To define a new class, we began by writing the keyword class
and then the constant SuperCar
. Note that the constant for a class MUST start with a capitalized letter.
The class SuperCar
contains the general structure and functions that each instance of this car has. This means that car_1, car_2, and car_3 each has the variables @make
, model
, @year
, @hp
, and @tq
; and can use the methods initialize
and printer_specs
. It is important to note that car_1, car_2, and car_3 are not just limited to just these two methods. There are other ways to add new methods to these objects, which are not covered in this post.
Another thing that you see here are instance variables
. They are the “properties” of the class, and each instance of the class has a different set of instance variables (i.e. car_1’s @make
is Ferrari
while car_2’s @make
is Lamborghini
). Instance variables can be used anywhere within the instance of the class. In the example, the initialize
method stores the 5 parameters from initializing a new SuperCar
into 5 instance variable assignments. These instance variables can be used in the print_spec
method, as well as any other method you decide to create from within the class.
You’d call an instance method that you’ve created in the new class with the .
notation, the same way you’d call an instance method from the built-in classes, such as Integers, Arrays, and Hashes. Here is an example of an instance method call and what is displayed on the console:
car_1.print_spec >>"This 2013 Ferrari 458 Italia has 570 horsepower and 398 lb-ft of torque."
ar_2.print_spec >>"This 2012 Lamborghini Aventador has 691 horsepower and 508 lb-ft of torque."
While an object cannot belong to more than one class, a class can be a descendant of another class. Descendant classes inherit all of the instance methods from the ancestor class, as well as the ancestor of the ancestor class, and so on.
For example, a certain super car collector takes a portion of his super cars to the racetracks:
class TrackCar < SuperCar def set_laptime=(time) @laptime = time end def get_laptime @laptime end end car_4 = TrackCar.new('Ferrari','458 Italia Speciale',2014,597,398)
Again, we have several pieces of code to look at here. In the first piece, I created a class called TrackCar
and used the <
notation to specify that TrackCar is a descendant of the SuperCar class. This class has two methods: set_laptime
(this is a setter method) and get_laptime
(and this is a getter method). A setter method allows you to set an instance variable to a value and a getter method allows you to get the value of an instance variable.
Notice that the set_laptime
method looks a little funky. Ruby allows you to use the =
notation in instance methods to make calling it look more reader-friendly and consistent with variable assignment conventions (i.e. car_4.set_laptime = 98
as opposed to car_4.set_laptime(98)
). There is another shortcut to write setter and getter methods, using attr_
attributes (to learn more about them, you can start here).
In the last piece of the code, I created an instance of TrackCar
called car_4. Now, let’s run several methods:
car_4.print_specs >>"This 2014 Ferrari 458 Italia Speciale has 597 horsepower and 398 lb-ft of torque."
car_4.set_laptime = 98
puts "This car's fastest lap time is #{car_4.return_laptime} seconds." >>"This car's fastest lap time is 98 seconds."
Notice that the print_specs
method works even though it was not written in the TrackCar
class. This is because TrackCar is a descendant of SuperCar. Any instance of the class TrackCar
can use methods from its ancestor classes. If you do not specify an ancestor class, it will default to the class Object
. Object
is a descendant of BasicObject
, which is at the top of the Ruby class hierarchy. That means that all Ruby classes eventually go up to Object
and then BasicObject
.
This is a good place to stop. We’ve talked about classes, instances, instance variables, instance methods, and class inheritance. To summarize it all, as tutorialspoint puts it, “A class is essentially a blueprint from which individual objects are created.”
This blog has been initially published on tonymai.github.io.