A Beginner's Guide to understanding Object Oriented Programming (OOP) in Ruby

Dumebi Okolo - Nov 14 '23 - - Dev Community

In this guide, we'll delve into the key principles of Object Oriented Programming in Ruby, exploring classes, objects, inheritance, encapsulation, and polymorphism in Ruby.

Table of Contents

 1. What is Object Oriented Programming in Ruby
 2. Understanding Classes and Objects in Ruby

       2.1. Classes: Blueprints for Objects

             a. Understanding Classes in Ruby

             b. Creating instances from a Class

             c. Using Methods of Objects
 3. Inheritance in Ruby: Sharing Traits
 4. Encapsulation in Ruby: Keeping Secrets

 5. Polymorphism in Ruby: Many Faces

      5.2 Method Overriding in Ruby
 6. Abstraction in Ruby
 7. Conclusion

       7.3. Unveiling the Power of Classes and Objects

       7.4. Embracing the Dynamic Force of Polymorphism

       7.5. The Ongoing Coding Odyssey

What is Object Oriented Programming in Ruby

Image of object oriented programming in Ruby
Object-Oriented Programming (OOP) is like organizing your code using building blocks called "objects." These objects have special powers—they can store information and perform actions. In Ruby, a programming language known for its simplicity, OOP is a key feature.

Understanding Classes and Objects in Ruby

understanding classes and objects in Ruby

Classes in Ruby: Blueprints for Objects

In OOP, a class acts as a blueprint or template for creating objects. It defines the structure and behavior that the objects based on it will possess. These objects are called instances of the class. Think of a class as a recipe for making pasta, and the instances as the various dishes of pasta that is being made.

Understanding Classes in Ruby

A class typically includes the following components:

  1. Class Declaration: It starts with the keyword class followed by the name of the class. Class names in Ruby are typically written in CamelCase.

    class Dog
    
  2. Constructor Method (initialize): The initialize method is a special method that gets called when a new object is created from the class. It's used to set up the initial state of the object.

    def initialize(name, age)
      @name = name
      @age = age
    end
    

    In this example, name and age are parameters passed when creating a new Dog object.

  3. Instance Variables (@name, @age): These variables store the state of the object. They have an @ symbol before their names, indicating that they belong to the instance of the class.

    @name = name
    @age = age
    
  4. Methods: These are functions defined within the class. They represent the behavior or actions that objects created from the class can perform.

    def bark
      puts "Woof, woof!"
    end
    
    def details
      puts "Name: #{@name}, Age: #{@age}"
    end
    

    Here, bark and details are methods that a Dog object can call to perform specific actions.

Creating instances from a Class

Once a class is defined, you can create instances or objects based on that class. Objects are instances of a class, and each object has its own state and behavior.

dog1 = Dog.new("Buddy", 3)
dog2 = Dog.new("Max", 5)
Enter fullscreen mode Exit fullscreen mode

Here, dog1 and dog2 are instances of the Dog class. The initialize method is called automatically when these objects are created, setting up their initial state.

Using Methods of Objects

Objects created from a class can invoke its methods:

dog1.bark
dog2.details
Enter fullscreen mode Exit fullscreen mode

In this example, dog1 barks, and dog2 provides details. Each object can use the methods defined in the class, but the specific details might be different based on the state of the object.

Inheritance in Ruby: Sharing Traits

Inheritance is like passing on traits from parents to children. In Ruby, a class can inherit traits from another class. Let's see how:

class Animal
  def initialize(name)
    @name = name
  end

  def speak
    puts "Some generic sound"
  end
end

class Cat < Animal
  def speak
    puts "Meow!"
  end
end
Enter fullscreen mode Exit fullscreen mode

Here, Cat is like a child inheriting traits from its parent (Animal). It can still do everything an Animal can, but it has its own unique way of speaking.


generic_animal = Animal.new("Generic Animal")
generic_animal.speak

my_cat = Cat.new("Whiskers")
my_cat.speak
Enter fullscreen mode Exit fullscreen mode

Just like how a cat inherits traits from an animal, our my_cat speaks in a cat-like way.

Encapsulation in Ruby: Keeping Secrets

Encapsulation is like putting your code in a secret box. It keeps things organized and prevents others from messing with your stuff. Let's see how it works:


class Book
  attr_accessor :title, :author

  def initialize(title, author)
    @title = title
    @author = author
  end

  def details
    "Title: #{@title}, Author: #{@author}"
  end
end
Enter fullscreen mode Exit fullscreen mode

Here, Book is like a secret box. It has methods (details) that let you see what's inside, but you can't directly mess with the title or author unless you use the provided methods.


my_book = Book.new("Ruby Programming", "John Doe")
puts my_book.details

my_book.title = "Mastering Ruby"
puts my_book.details
Enter fullscreen mode Exit fullscreen mode

You can see what's inside the my_book box using the details method. And you can change the title, but only through the method provided.

Polymorphism in Ruby: Many Faces

Polymorphism is a fascinating aspect of OOP (Object Oriented Programming) that allows objects to be treated as instances of their parent class, even when they are instances of a child class. It's like using different things interchangeably. In Ruby, polymorphism is often seen through method overriding.

Method Overriding in Ruby

Method overriding occurs when a child class provides a specific implementation for a method that is already defined in its parent class. This allows objects of the child class to be used in a way that is interchangeable with objects of the parent class.

Let's illustrate this with an example:

class Animal
  def speak
    puts "Some generic sound"
  end
end

class Cat < Animal
  def speak
    puts "Meow!"
  end
end
Enter fullscreen mode Exit fullscreen mode

Here, Cat is a child class of Animal. The speak method is overridden in the Cat class to provide a cat-specific sound. Now, both Animal and Cat objects can be used interchangeably.

generic_animal = Animal.new
generic_animal.speak  # Outputs: Some generic sound

my_cat = Cat.new
my_cat.speak          # Outputs: Meow!
Enter fullscreen mode Exit fullscreen mode

Even though generic_animal and my_cat are instances of different classes, they both respond to the speak method. This is polymorphism in action.

Polymorphism in Ruby allows objects to be treated as instances of their parent class, enabling flexibility and interchangeability in the use of objects. It's a powerful concept that enhances the adaptability and extensibility of your code.

Abstraction in Ruby

In Ruby, abstraction is about simplifying complex code by focusing on what objects do rather than how they do it. It's achieved through abstract classes or interfaces.

  1. Abstract Classes:
    • Use the abstract_class gem or convention.
    • Define abstract methods without implementations.
    • Subclasses must provide implementations.
   require 'abstract_class'

   class Animal
     abstract_class

     def speak
       raise NotImplementedError, 'Subclasses must implement speak'
     end
   end

   class Dog < Animal
     def speak
       puts 'Woof!'
     end
   end

   class Cat < Animal
     def speak
       puts 'Meow!'
     end
Enter fullscreen mode Exit fullscreen mode
  1. Interfaces in Ruby:
    • Use modules to create interfaces.
    • Modules define methods classes must implement.
   module Speakable
     def speak
       raise NotImplementedError, 'Classes must implement speak'
     end
   end

   class Dog
     include Speakable

     def speak
       puts 'Woof!'
     end
   end

   class Cat
     include Speakable

     def speak
       puts 'Meow!'
     end
Enter fullscreen mode Exit fullscreen mode

Abstraction simplifies code, making it more modular and easier to maintain by focusing on essential features rather than implementation details.

Conclusion

In our exploration of Ruby's Object-Oriented Programming (OOP), we've traversed the landscapes of classes, objects, inheritance, encapsulation, polymorphism, and the dynamic realm of class variables. As we conclude this comprehensive journey, let's reflect on the essence of our coding odyssey.

Unveiling the Power of Classes and Objects

Classes as Architects: In Ruby, classes transcend their role as blueprints; they are architects designing living, breathing entities. With each class, we create not just structures but dynamic realms filled with unique and captivating objects.

Objects as Dynamic Entities: Every object born from a class is a dynamic entity with its own story, featuring distinct attributes and action-packed methods. Like characters in a novel, these objects add depth and richness to our code, making it not just functional but expressive.

Embracing the Dynamic Force of Polymorphism

Polymorphism as a Symphony: Polymorphism emerges as a symphony conductor, orchestrating a harmonious collaboration of methods. Through method overriding, our code adapts, evolves, and performs dynamic feats, akin to a mesmerizing symphony where each instrument plays a unique part.

The Ongoing Coding Odyssey

As we conclude this exploration, remember that coding is an ongoing odyssey. The knowledge gained here is not just a toolkit; it's a compass guiding you through the vast and ever-expanding landscape of Ruby's OOP. With every line of code, you have the opportunity to craft intricate narratives, build interconnected universes, and truly master the art of Object-Oriented Programming.

Happy Coding!

Let's connect on LinkedIn.
Follow me on X (formerly Twitter)

aiAssistedArticle

Cover photo
Image: OOP in Ruby
Image: understanding classesand objects in Ruby

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .