Koren Leslie Cohen

  • About
  • Blog
  • Contact

0 comments

Ruby / Rails

Ruby Classes

May 28, 2014 by Koren Leslie Cohen

rails

Common classes in Ruby include objects such as strings, integers and arrays.  We can also create new classes in Ruby.

Why use a Ruby class?

Classes are useful to help organize objects with similar attributes and methods.  Instead of defining multiple objects with similar attributes, we can instead define a single class and create instances of that class.

Defining a Class

A Ruby class is defined simply by class followed by the class name, written in CamelCase. Follow this by end and you have created a new class:

class Animals
end
Creating Class Objects

Objects can be thought of as members or instances of the class.  For example, we could create new objects/instances of the Animals class with the following:

pig = Animals.new
sheep = Animals.new
elephant = Animals.new

Pig, sheep and elephant are now objects of the class Animals.

Initialize Method

If we want each object of the Animals class to have certain attributes, we can initialize the class using an initialize method.  The initialize method will then pass the attributes of the class to .new:

class Animals
    @@no_of_animals = 0
    def initialize(name, color=nil)
        @name = name
        @color = color
    end
end

Two things to note about the above code:

(1) The initialize method takes two arguments, called parameters: name  and color.  In order to accept a new object by just its name, the color parameter is set to nil, which makes it an optional parameter.  This means that to create a new object of the class Animals, we would need to pass in at least the parameter name and, if we choose, the parameter color.  pig = Animals.new(“Wilbur”) would be sufficient, and the following would also work: pig = Animals.new(“Wilbur”, “pink”).

(2) @name and @color are instance variables whose values are set to the parameters of the initialize method.  @@no_of_animals  is a class variable which will keep track of how many animals there are in the class.  It is important to know the difference between variable types when working with classes.

Variables

local – A local variable is defined inside a method and is unavailable outside the method.

@instance  – An instance variable (declared with @) is available across all methods for a particular instance or object and can be applied to each object of the class.  Instance variables exist as long as the object exists.

@@class  – Class variables (declared with @@) are available across different objects of the same class.  There is only one class variable throughout the class, so these variables are often used for counting or keeping track of how many instances of a class have been created.

$global  – Global variables (declared with $) are available across all classes and can be modified from anywhere in the program.  These should be used sparingly, if at all.

Getter & Setter Methods

“Getter” and “setter” methods allow us to access Ruby variables inside a class.  In our Animals class, if we wanted to access @name  or @color, or set/modify the value of these variables, we would need methods as follows:

class Animals
    @@no_of_animals = 0
    def initialize(name, color=nil)
        @name = name
        @color = color
    end

    def name  # getter method
        @name
    end

    def color  # getter method 
        @color
    end

    def name=(value)  # setter method
        @name = value
    end

    def color=(value)  # setter method
        @color = value
    end
end

As you can see, this requires quite a bit of code, especially when there is a more efficient way to accomplish this.

Attribute Accessors

Attribute accessors are shorthand for getter and setter methods.  They allow us to access and modify our instance variables by passing them to the attribute accessors as symbols.  There are three types:

attr_reader  is a method that replaces the “getter” method above.  It takes any number of parameters and, for each parameter, defines a “getter” method that returns the instance of the variable with the same name.  attr_reader :variable  returns:

def variable
    @variable
end

attr_writer  is a method that replaces the “setter” method above.  attr_writer :variable   returns:

def variable=(value)
    @variable = value
end

Finally, attr_accessor  is both a getter and a setter, as it performs the functions of both the attr_reader  and attr_writer  methods.  attr_accessor :variable  is the same as:

attr_reader :variable
attr_writer :variable

Using the class Animals, this streamlines our code:

class Animals
    attr_accessor :name
    attr_accessor :color

    @@no_of_animals = 0

    def initialize(name, color=nil)
        @name = name
        @color = color
    end
end

Now, we are able to read and write @name and @color without the tedious task of coding each method individually.

Inheritance

Sometimes we want to create a new class which has the same methods and attributes of a class we previously created.  We can accomplish this through inheritance.

class New < Old
end

In the above code, < is a symbol meaning “inherit from”, and class New would inherit the methods and attributes of class Old.  Class New would be the subclass, and class Old would be the parent class, or superclass.

Override

What happens if class New inherits a method from class Old that it cannot use?  Or perhaps class New functions slightly differently from class Old, and we would need to create a method in class New to override a method in class Old.  There is an easy solution to this.

For example, if class New inherited the following method from class Old:

def welcome
    return "Welcome to class Old!"
end

Instead of creating a new method which would override this and hanging onto an old method which would never be used, we can simply modify the method as follows:

def welcome
    return "Welcome to class New!"
end

The new method would override, or replace, the inherited method.

Super

Sometimes, when working with a subclass, we may overwrite a method or attribute inherited from a parent or superclass. super allows us to directly access the attribute or method of the parent or superclass:

def welcome
    puts "Welcome to class New!"
    super
end

Unlike other languages, Ruby only allows for one superclass per class.  Attempting to inherit from more than one class will result in an error.

Public, Private & Protected Methods

In Ruby, a class’s instance methods are public by default.  The initialize method is private by default.  If you want to make a method private, you simply declare private above the method.  This makes the particular method private to the object where it’s defined, and it can only be called from other code inside that object.  Protected methods are designated by declaring protected above the method, and can be invoked only by objects of the defining class and subclasses.

Instance vs. Class Methods

Each of the methods in the above examples is an instance method.  Instance methods reside at the object level, whereas class methods reside at the class level.  Simply creating a method inside a class creates an instance method.  To create a class method, you would have to either use the class name:

class Animals
    def Animals.welcome
        puts "welcome is now a class method"
    end
end

Or you could use self:

class Animals
    def self.welcome
        puts "welcome is now a class method"
    end
end

self is the preferred method among Ruby developers, as it does not repeat the class name in the method (which would violate DRY – Don’t Repeat Yourself).  If the class name were to be changed later, you would also have to change the name inside each class method.

But what is self?

Self

self is used to refer to the object which holds it.  In the above example, the object holding self is the class Animal, so calling self.welcome calls a class method, or a method on the object holding self.  Because, remember…

Although classes are used to organize objects with similar attributes and methods, a class is itself an object in Ruby.

  • About
  • Latest Posts
Connect
Koren Leslie Cohen
Product manager at Facebook. Former senior product manager at Dollar Shave Club in Los Angeles and software engineer at J.Crew / Madewell in New York City. Recovering trial lawyer.
Connect
Latest posts by Koren Leslie Cohen (see all)
  • PM Career Story - April 28, 2022
  • How to Transition into Product Management - December 26, 2017
  • What I’ve Learned in My First Few Months as a Product Manager - October 14, 2015

Related Posts

FizzBuzz in Ruby (and the Strangeness of Ruby Loops)
Rails: Uploading Photos via Amazon S3 and Paperclip

Share

Facebook Google+ Twitter Pinterest Email

Comments Cancel reply

Your email address will not be published. Required fields are marked *

*

code

Back to Blog

  • GitHub
  • Instagram
  • LinkedIn
  • RSS
  • Twitter

Looking for something?

Copyright 2023 Koren Leslie Cohen