Table of contents
1.
Introduction
2.
new, allocate, and initialize
3.
Class::new and Class#new
4.
Factory Methods
5.
dup, clone, and initialize_copy 
6.
 marshal_dump and marshal_load 
7.
The Singleton Pattern
8.
Frequently Asked Questions
8.1.
In Ruby, how do you define a class method?
8.2.
How should a class be structured in Ruby?
8.3.
What does Ruby's class variable mean?
8.4.
What are Class Instance Variables?
8.5.
Define Class Instance Variables?
9.
Conclusion
Last Updated: Mar 27, 2024
Medium

Object creation and initialization in ruby

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Let’s first understand what Ruby is before moving on to the object creation and initialization in Ruby.

What is Ruby

Ruby is a high-level, general-purpose, interpreted programming language that supports a variety of programming paradigms. It was created with a focus on simplicity and productivity in programming. Everything including the primitive data types also, is an  object in Ruby.

Building desktop applications, static websites, data processing services, and even automation solutions is a breeze with Ruby. Web servers, DevOps, web scraping, and crawling are all uses for it.

Object Creation and Initialization in Ruby

Now let’s talk about Objects and their creation in Ruby.

Objects are instances of the class. Now, you'll discover how to make objects in Ruby that belong to a class. The new method of the class can be used to create objects in Ruby. The Ruby library has a special kind of predefined method called new. Here the new method is a member of the class methods.

Now, let us discuss about the initialization in detail: 

new, allocate, and initialize

The class method new is inherited by all classes. This method has two tasks:  

  • Allocating a new object, or creating the object from scratch
  • initialising the object

 

These two tasks are given, respectively, to the allocation and initialise procedures. So now the question arises how to define a new class?…it’s easy let us see how we will not only define a new class but we will also learn about initialising it.

 

class Ninja #here we are defining a class Ninja
  def initialize(name)  #with the help of initialize method we will pass argument
  end
end

 

Class Example

All class objects inherit the allocate method, which is an instance method of Class. To create fresh instances of a class, use this method on your own. Try not to override it, though, as Ruby always calls this method directly and disregards any overridden versions you might have written.

Now that we know the new method and allocation method let us understand how initialization will work here.

 

def new(*args)
  obj = self.allocate        # Create a new object of this class
  obj.initialize(*args)      # Call the object's initialize method with our args
  obj                              # Return new object; ignore return value of initialize
end 

 

The initialise method typically creates instance variables for the object and sets their initial values. Usually, the arguments that the client code passed to new and that new passed to initialise are used to determine the value of these instance variables. 

Class::new and Class#new

As we have already discussed, every instance of the class Class that exists in Ruby is a first-class object. An object of type Class is initialised and assigned to a global constant when a new class is formed. Class defines two new methods. 
 

  • Class#new which is an instance method 
  • Class::new is a class method 

 

The first one is the instance approach which is used to generate class methods that are inherited by all class objects and become class methods of the class and generate new instances.

The class procedure Class::new is the method specific to the Class class, and it can be applied to create new classes.

Factory Methods

A creational design pattern called the factory method addresses the issue of creating product objects without specifying their concrete classes. Allowing instances of a class to be initialised in many ways is often useful. This helps us to provide flexibility in the code.

Frequently, you can accomplish this by giving initialise method parameter defaults. You can invoke new with two or three arguments, for instance, if the initialise method is specified.

It establishes an interface for object creation, but leaves it up to subclasses to decide the class to instantiate. A class can defer its own instantiation to subclasses by using the Factory function.

Now let’s discuss the steps for a factory method.

Initially the Creator class declares the factory method that is supposed to return an object of a Product class. The Creator's subclasses usually provide the implementation of this method. As in this example class Ninja is the creator class.

 

class Ninja
  def take_action
    # the #get_new_powers method, defined in subclasses of Ninja, is our   
 # factory method / template method. It determines which action is created.
    action = get_new_powers
    action.take!  # each action class has a #take! method
  end
 end

 

Also note that, despite its name, the Creator's primary responsibility is not creating products. Usually, it contains some core business logic that relies on Product objects, returned by the factory method. Subclasses can indirectly change that business logic by overriding the factory method and returning a different type of product from it.

Factory Methods

In the illustration above, the Creator class, which needs a Product object, does not directly instantiate the Product1 class. The Creator is independent of the concrete class that is instantiated because it uses a different factoryMethod() to create a product object. 

Class to be instantiated can be modified by Creator subclasses. By creating an instance of the Product1 class, the Creator1 subclass in this illustration implements the abstract factoryMethod().

dup, clone, and initialize_copy 

The dup and clone methods are another ways by which new objects are created. These methods allocates a new instance of the object's class whenever they are invoked. They then transfer the receiving object's taint and all of its instance variables to the newly allocated object. 

dup vs clone image

Clone takes one step farther than dup in terms of copying; it copies the receiver object's singleton methods as well and freezes the copy object if the original is already frozen.If you want to change an object but keep a copy of the original then you can clone it.

Let’s say we want to print an array with all the elements but the first one.So we can do the same using clone method as in the give example

Example image
y = x.clone
y.shift
# [1]
y
# [2,3,4,5]

 

Clone and dup will invoke the initialize copy method on the copied object after copying the instance variables from the original if a class defines that method.   

The original object is passed as an argument to the initialise copy method, giving it the opportunity to modify any changes in the copied object. However, it is unable to create its own copy object; the initialize copy return value is disregarded. 

You can use #dup which creates a shallow copy of the object, meaning "the instance variables of the object are copied, but not the objects they reference." 

For instance:

a = [2, 4, 6]
b = a.dup
b   # => [2, 4, 6]

 marshal_dump and marshal_load 

The method marshal dump will be invoked when dumping an object. The information required by marshal load to recreate the object must be returned by marshal dump as a consequence. Any object could be the result.

When marshal dump is used to load an object, the object must first be allocated before marshal load can be called with the marshal dump result. The object must be recreated using marshal load using the data from the result.

 

hello_world = 'hello world!'
puts "Hey Ninja!"
serialized_string = Marshal.dump(hello_world) 
serialized_string.class                       # => String
deserialized_hello_world = Marshal.load(serialized_string) # => "hello world!"
puts hello_world.object_id              # => 70204420126020
puts deserialized_hello_world.object_id # => 70204419825700

 

Output:

output image

For the purpose of serialising our string, we will here invoke the Marshal.dump module method. Our serialised string is contained in the return value, which is where we keep it. A file that contains this string can then be used to recreate the original object in a different process. The original object is then rebuilt using the byte stream by calling the Marshal.load method.

We can see that the object id of this newly constructed string is different from the object id of the hello world string, indicating that even though it is a distinct object, the data it contains is the same.

The Singleton Pattern

A class called a singleton only has a single instance. In an object-oriented framework, singletons can be used as useful alternatives for class methods and class variables to store global program state. A number of the techniques shown before are required for properly implementing a singleton. Dup and clone must not be allowed to make copies, the new and allocate methods must be made private, and so on.

Fortunately, the Singleton module in the standard library handles this work for us; just require 'singleton' and then include Singleton into your class. This specifies the class method instance, which returns the class's singular instance and accepts no arguments. Define a method called initialize to perform class initialization on the single instance.

Simply hide the function Object() { [native code] } and add a static creation function to implement a shoddy Singleton. In a multithreaded environment, the same class behaves wrong. The creation method can be called simultaneously by several threads, producing multiple instances of the Singleton class.

 

# The Singleton class defines the `instance` method that lets clients access the
# unique singleton instance.
class Singleton
  @instance = new
  private_class_method :new
  # The static method that controls the access to the singleton instance.
  #
  # This implementation let you subclass the Singleton class while keeping just
  # one instance of each subclass around.
  def self.instance
    @instance
  end


  # Finally, any singleton should define some business logic, which can be
  # executed on its instance.
  def some_business_logic
    # ...
  end
end


# The client code.


s1 = Singleton.instance
s2 = Singleton.instance


if s1.equal?(s2)
  print 'Singleton works, both variables contain the same instance.'
else
  print 'Singleton failed, variables contain different instances.'
end

 

Output:

Frequently Asked Questions

In Ruby, how do you define a class method?

Public class methods can be accessed with the help of objects and are defined inside the class. When a method is defined outside of the class definition, it is by default marked as private. Methods are marked as public by default, as specified in the class definition.

How should a class be structured in Ruby?

Three things make up a Ruby object: a class, some instance variables, and a set of flags. A Ruby class is an object of the class Class, which includes all object-related objects things as well as a list of methods and a reference to a superclass (which is itself another class).

What does Ruby's class variable mean?

Declared variables are used within class. There are 2 different types: class variables, or static variables, which have the same value for all instances of the class, and instance variables, which vary depending on the instance of the object.

What are Class Instance Variables?

Instance variables are accessible across all methods for any given instance or object. That is, instance variables vary from object to object. Instance variables are denoted by the at sign (@) and the variable name.

Define Class Instance Variables?

All methods for any given instance or object have access to all methods for any of the instance variables. Instance variables, then, differ from one object to another. The at sign (@) and the variable name are used to identify instance variables.

Conclusion

In this article, we have discussed Object Creation and Initialization in detail. 

We hope that this article has helped you enhance your knowledge regarding classes of Ruby. If you would like to learn more, check out our articles on Tainting Objects in RubyObject References in RubyRuby-langmore-on-ruby-langruby-lang.faqrubykoans and  many more. 

  logo image 

Refer to our guided paths on Coding Ninjas Studio to learn more about DSA, Competitive Programming, JavaScript, System Design, etc. Enrol in our courses and refer to the mock test and problems available, Take a look at the interview experiences and interview bundle for placement preparations.

Do upvote our blog to help other ninjas grow.

Happy Learning!

Live masterclass