Object-oriented programming reduces the complexity of large programming software thus making the software easier to maintain. In a pure object-oriented language, everything inside an Object. The goal of OOPs is to combine the data and functions which are operating those data so that the data cannot be accessed by any other part of the code.
Ruby is a pure Object oriented language and everything is considered as an object. Primitve types Strings, Numbers, true or false are also an Object.
OOP's concepts
Class is nothing but a blueprint of a data type. It simply defines, what an instance of the class consists and possible functions which can be performed on the object of the class. In Ruby, even classes are objects of "class" class
A class definition starts with the keyword class followed by the class name and is delimited with an end. For example, we defined the Box class using the keyword class as follows
class Table
code
end
|
The name must begin with a capital letter and by convention names that contain more than one word are run together with each word capitalized and no separating characters (CamelCase).
A class provides the blueprints for objects, so basically an object is created from a class. We declare objects of a class using new keyword. Following statements declare two objects of class Table
tab1 = Table.new
tab2 = Table.new
|
The initialize method is a standard Ruby class method and works almost same way as constructor works in other object oriented programming languages. The initialize method is useful when we want to initialize some class variables at the time of object creation. This method may take a list of parameters and like any other ruby method it would be preceded by def keyword as shown below
class Box
def initialize(w,h)
@width, @height = w, h
end
end
|
The instance variables are kind of class attributes and they become properties of objects once objects are created using the class. Every object's attributes are assigned individually and share no value with other objects. They are accessed using the @ operator within the class but to access them outside of the class we use public methods, which are called accessor methods. If we take the above defined class Table then @width and @height are instance variables for the class Table
class Table
def initialize(w,h)
# assign instance variables
@width, @height = w, h
end
end
|
To make the variables available from outside the class, they must be defined within accessor methods, these accessor methods are also known as a getter methods. Following example shows the usage of accessor methods
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# accessor methods
def printWidth
@width
end
def printHeight
@height
end
end
# create an object
table= Table.new(10, 20)
# use accessor methods
x = table.printWidth()
y = table.printHeight()
puts "Width of the table is : #{x}"
puts "Height of the table is : #{y}"
|
Output
Width of the table is : 10
Height of the table is : 20
|
Similar to accessor methods, which are used to access the value of the variables, Ruby provides a way to set the values of those variables from outside of the class using setter methods, which are defined as below
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# accessor methods
def getWidth
@width
end
def getHeight
@height
end
# setter methods
def setWidth=(value)
@width = value
end
def setHeight=(value)
@height = value
end
end
# create an object
table= Table.new(10, 20)
# use setter methods
table.setWidth = 30
table.setHeight = 50
# use accessor methods
x = table.getWidth()
y = table.getHeight()
puts "Width of the table is : #{x}"
puts "Height of the table is : #{y}"
|
Output
Width of the table is : 30
Height of the table is : 50
|
The instance methods are also defined in the same way as we define any other method using def keyword and they can be used using a class instance only as shown below. Their functionality is not limited to access the instance variables, but also they can do a lot more as per our requirement
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# create an object
table= Table.new(10, 20)
# call instance methods
a = table.getArea()
puts "Area of the tableis : #{a}"
|
Output
Area of the table is : 200
|
The class variables is a variable, which is shared between all instances of a class. In other words, there is one instance of the variable and it is accessed by object instances. Class variables are prefixed with two @ characters (@@). A class variable must be initialized within the class definition as shown below.
A class method is defined using def self.methodname(), which ends with end delimiter and would be called using the class name as classname.methodname
#!/usr/bin/ruby -w
class Table
# Initialize our class variables
@@count = 0
def initialize(w,h)
# assign instance avriables
@width, @height = w, h
@@count += 1
end
def self.printCount()
puts "Table count is : #@@count"
end
end
# create two object
table1= Table.new(10, 20)
table2= Table.new(30, 100)
# call class method to print table count
Table.printCount()
|
output
Table count is : 2
|
Any class we define should have a to_s instance method to return a string representation of the object. Following is a simple example to represent a Table object in terms of width and height
#!/usr/bin/ruby -w
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# define to_s method
def to_s
"(w:#@width,h:#@height)" # string formatting of the object.
end
end
# create an object
table= Table.new(10, 20)
# to_s method will be called in reference of string automatically.
puts "String representation of table is : #{box}"
|
output
String representation of table is : (w:10,h:20)
|
Ruby gives us three levels of protection at instance methods level, which may be public, private, or protected. Ruby does not apply any access control over instance and class variables.
Public Methods − Public methods can be called by anyone. Methods are public by default except for initialize, which is always private.
Private Methods − Private methods cannot be accessed, or even viewed from outside the class. Only the class methods can access private members.
Protected Methods − A protected method can be invoked only by objects of the defining class and its subclasses. Access is kept within the family.
Following is a simple example to show the syntax of all the three access modifiers
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method by default it is public
def getArea
getWidth() * getHeight
end
# define private accessor methods
def getWidth
@width
end
def getHeight
@height
end
# make them private
private :getWidth, :getHeight
# instance method to print area
def printArea
@area = getWidth() * getHeight
puts "Big Table area is : #@area"
end
# make it protected
protected :printArea
end
# create an object
table= Table.new(10, 20)
# call instance methods
a = table.getArea()
puts "Area of the table is : #{a}"
# try to call protected or methods
table.printArea()
|
Output
Area of the table is : 200
test.rb:42: protected method `printArea' called for #
<Box:0xb7f11280 @height = 20, @width = 10> (NoMethodError)
|
One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application.
Inheritance also provides an opportunity to reuse the code functionality and fast implementation time but unfortunately Ruby does not support multiple levels of inheritances but Ruby supports mixins. A mixin is like a specialized implementation of multiple inheritance in which only the interface portion is inherited.
When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class or superclass, and the new class is referred to as the derived class or sub-class.
Ruby also supports the concept of subclassing, i.e., inheritance and following example explains the concept. The syntax for extending a class is simple. Just add a < character and the name of the superclass to our class statement. For example, following define a class BigTable as a subclass of Table
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# define a subclass
class BigTable < Table
# add a new instance method
def printArea
@area = @width * @height
puts "Table box area is : #@area"
end
end
# create an object
table= BigTable.new(10, 20)
# print the area
table.printArea()
|
output
Big table area is : 200
|
Though we can add new functionality in a derived class, but sometimes we would like to change the behavior of already defined method in a parent class. We can do so simply by keeping the method name same and overriding the functionality of the method
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# define a subclass
class BigTable < Table
# change existing getArea method as follows
def getArea
@area = @width * @height
puts "Big table area is : #@area"
end
end
# create an object
table= BigTable.new(10, 20)
# print the area using overriden method.
table.getArea()
|
We'd like the + operator to perform vector addition of two Table objects using +, the * operator to multiply a Table width and height by a scalar, and the unary - operator to do negate the width and height of the Table
class Table
def initialize(w,h) # Initialize the width and height
@width,@height = w, h
end
def +(other) # Define + to do vector addition
Table.new(@width + other.width, @height + other.height)
end
def -@ # Define unary minus to negate width and height
Table.new(-@width, -@height)
end
def *(scalar) # To perform scalar multiplication
Table.new(@width*scalar, @height*scalar)
end
end
|
Sometimes, we want to prevent an object from being changed. The freeze method in Object allows us to do this, effectively turning an object into a constant. Any object can be frozen by invoking Object.freeze. A frozen object may not be modified: we can't change its instance variables.
We can check if a given object is already frozen or not using Object.frozen? method, which returns true in case the object is frozen otherwise a false value is return
#!/usr/bin/ruby -w
# define a class
class Table
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# accessor methods
def getWidth
@width
end
def getHeight
@height
end
# setter methods
def setWidth=(value)
@width = value
end
def setHeight=(value)
@height = value
end
end
# create an object
table= Table.new(10, 20)
# let us freez this object
table.freeze
if( table.frozen? )
puts "Table object is frozen object"
else
puts "Table object is normal object"
end
# now try using setter methods
table.setWidth = 30
table.setHeight = 50
# use accessor methods
x = table.getWidth()
y = table.getHeight()
puts "Width of the table is : #{x}"
puts "Height of the table is : #{y}"
|
Output
Table object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
from test.rb:39
|
We can define a constant inside a class by assigning a direct numeric or string value to a variable, which is defined without using either @ or @@. By convention, we keep constant names in upper case.
Once a constant is defined, we cannot change its value but we can access a constant directly inside a class much like a variable but if we want to access a constant outside of the class then we would have to use classname::constant
#!/usr/bin/ruby -w
# define a class
class Table
TABLE_COMPANY = "TATA Inc"
TABLEWEIGHT = 10
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# create an object
table= Table.new(10, 20)
# call instance methods
a = table.getArea()
puts "Area of the table is : #{a}"
puts Table::TABLE_COMPANY
puts "Table weight is: #{Table::TABLEWEIGHT}"
|
Output
Area of the table is : 200
TATA Inc
Table weight is: 10
|
There may be a situation when we want to create an object without calling its constructor initialize i.e. using new method, in such case we can call allocate, which will create an uninitialized object
#!/usr/bin/ruby -w
# define a class
class Table
attr_accessor :width, :height
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# create an object using new
table1 = Table.new(10, 20)
# create another object using allocate
table2 = Table.allocate
# call instance method using table1
a = table1.getArea()
puts "Area of the table is : #{a}"
# call instance method using table2
a = table2.getArea()
puts "Area of the table is : #{a}"
|
Output
Area of the table is : 200
test.rb:14: warning: instance variable @width not initialized
test.rb:14: warning: instance variable @height not initialized
test.rb:14:in `getArea': undefined method `*'
for nil:NilClass (NoMethodError) from test.rb:29
|
Ruby program to add two integer numbers
how to create an array with Array.[](*args) in Ruby ?
What are the various Ruby runtimes, and how are they different?
Ruby program to check whether the given number is prime or not
Ruby program to reverse a string
Ruby program to check whether the given number is palindrome
Ruby program to print Fibonacci series
How to Replace array elements in Ruby?
Ruby program to print an array
Ruby program to check whether the given number is Armstrong
Program to Print Triangle of Numbers in Ruby
How to add/remove elements to Array in Ruby?
How to shuffle an array in Ruby?
Creating Array with Array.new(size, obj) in Ruby
Ruby program to generate random numbers
Ruby program to Calculate the factorial of given number
What are #method_missing and #send? Why are they useful?
How to Sort Array in Ruby?
How to get index of array element in Ruby
How to Get Input with Gets in Ruby
How to create two dimensional array in ruby?