3. Introduction
• Ruby is an object-oriented language in a very pure sense:
every value in Ruby is an object.
• Every object in ruby is an instance of a class.
• A class defines a set of methods that an object responds
to.
• Class may extend or subclass other classes, and inherit or
override the methods of their superclass.
• Classes can also include or inherit methods from-
modules.
• Ruby’s object are strictly encapsulated: their state can be
accessed only through the methods they define.
• Ruby’s classes are very open, Any ruby programs can add
methods to existing classes.
4. Creating the class
• Classes are created in ruby with the class keyword
Class Point
End
• Class definitions are delimited with an end.
• The class keyword creates a new constant to refer to
the class.
• Class names begin with capital letter like constants.
• Within the body of a class, but outside of any instance
methods defined by the class, the self keyword refers
to the class being defined.
• Like most statements in ruby, class is an expression.
The value of the class expression is the value of the last
expression within the class body.
5. Instantiating Point
• Empty classes can be instantiated
p = Point.new
• All class objects have a method named new that creates
a new instance.
• We can ask the new object what kind of it is since
nothing is defined in Point class.
p.class # => Point
p.is_a? Point # => true
6. Initializing Point
• In object oriented programming the initialization is done using
constructor. In Ruby, it is done with a initialize method.
class Point
def initialize(x,y)
@x=x
@y=y
end
end
• The initialize method has a special purpose, the new method
of the class object creates a new instance object and
automatically invokes the initialize method on that instance.
7. Contd..
• The initialize method expects two arguments, we must now supply
two values when we invoke Point.new
p = Point.new(0,0)
• In initialize method the x,y are assigned to instance variables @x,
@y.
• Each instance of our Point class has its own copy of these two
variables.
• The instance variables of an object can only be accessed by the
instance methods of that object.
• The to_s instance method should be defined to return a string
representation of the object. The representation is specified in the
method.
def to_s
“{#@x, #@y}”
End
8. Accessors and Attributes
• The values of these variables are only accessible only to the instance methods.
• We have to provide the accessor methods that return the value of the instance
variables.
def x
@x
end
def y
@y
end
• To make the point class to mutable, we would also add setter methods to set the
value of the instance variable.
def x=(value)
@x=value
end
def y = (value)
@y = value
end
9. Contd..
• This combination of instance variable with trivial getter and setter
methods is so common that Ruby provides a way to automate it.
• The attr_reader and attr_accessor methods are defined by the
Module class. All classes are modules, so you can invoke these
method inside any class definition.
• The attr_reader creates trivial getter methods for the instance
variables.
• The attr_accessor creates trivial getter and setter methods for the
instance variables.
class Point
attr_reader :x, :y
end
• The attr_reader and attr_accessor methods create the instance
methods.
10. Defining Operators
• We would like the + operator to perform vector addition of two
Point objects, the * operator to multiply a Point by scalar.
• The unary – operator to do the equivalent of multiplying by -1.
def +(other)
Point.new(@x+other.x, @y+other.y)
end
def –(other)
Point.new(-@x, -@y)
end
def *(value)
Point.new(@x*scalar, @y*scalar)
end
11. Array and Hash Access with []
• [] method for our class to allow Point objects to be treated
as read-only arrays of length 2 or read only hashs with key
:x, :y.
def [](index)
case index
when 0,-2: @x
when 1, -1: @y
when :x, “x”: @x
when :y, “y”: @y
else nil
end
end
12. Enumerating Co-ordinates
• We will define a each iterator of Point class. So
we can iterate through the co-ordinates like an
Array.
def each
yield @x
yield @y
end
p = Point.new(1,2)
p.each {|x| puts x} => 1
2
13. Point Equality
• Currently any two Point objects never going to be
equal to each other even if x and y coordinates
are same.
• To remove this we provide an implementation of
the == operator.
def ==(other)
if other.is_a? Point
@x==other.x && @y==other.y
else
false
end
end
14. Ordering Points
• To define this ordering for Point object, we need
only define the <=> operator and include the
Comparable module.
• Doing this mixes in implementations of the
equality and relational operators that are based
on our implementation of <=> operator we
defined.
include Comparable
def <=>(other)
return nil unless other.instance_of? Point
@x + @y <=> other.x + other.y
end
15. A Mutable Point
• The Point class we have been developing is immutable: once a Point
object has been created, there is no public API to change the X and Y
coordinates of that point.
• This can be done by changing attr_reader to attr_accessor
• We would like an alternative to the + operator to add two cordinates.
def add!(p)
@x+=p.x
@y+=p.y
self
end
def add(p)
q = self.dup
q.add!(p)
end
16. Class Variables
• Class variables are visible to, and shared by, the class methods and
the instance methods of a class and also by the class definition
itself.
• Like instance variables class variables are encapsulated.
class Point
@@n = 0
@@totalX = 0
@@totalY = 0
def intialize(x,y)
@x,@y = x,y
@@n +=1
@@totalX += x
@@totalY += y
end
17. continued
def self.report
puts “Number of points created: #{@@n}”
puts “Average X coordinates:
#{@@totalX/@@n}”
puts “Average Y coordinates:
#{@@totalY/@@n}”
end
• The thing to be noticed here is that class variables
are used in instance methods, class methods and
in the class definition itself, outside of any
method.
• Class variables are always evaluated in reference
to the class object created by the enclosing class
definition statement.
18. Class Method
• Class methods are the methods that are called on a class.
• To define a singleton method, use the def statement as usual, but specify
the object on which the method is to be defined as well as name of the
method.
def Point.sum(*points)
x = y = 0
points.each{|p| x+=p.x; y+=p.y}
Point.new(x,y)
End
• Class methods can also be defined using self keyword.
• Yet another technique for defining class methods is
class << self/Point
def sum(*points)
#code goes here
end
end
19. Class Instance Variables
• As we know classes are objects and can have instance variables just
as other objects can.
• The instance variables of a class are often called class instance
variables are not same as class variables.
• The class instance variables cannot be used inside instance methods
as class variables.
• These variables are not used much.
• The attr_reader and attr_accessor are used to create accessor
methods accordingly. Class methods are defined as
class << self
attr_accessor :a, :b
end
20. Method Visibility: Public, Protected, Private
• Methods are normally public unless they are explicitly declared to
be private or protected.
• A public method can be invoked from anywhere. There are no
restrictions on its use.
• A private method is internal to the implementation of a class and it
can only be called from the other instance methods of the class.
• Private methods are implicitly invoked on self, and may not
explicitly invoked on an object.
• A protected method is like a private method in that it can only be
invoked from within the implementation of a class or its subclass
and it is not restricted to implicit invocation on self.
21. Contd..
• Protected methods are the least commonly defined and also
the most difficult to understand.
• Public, private and protected are the instance methods for
module class.
• These methods can also be invoked with the names of one or
more methods as arguments.
protected :x
• Instance variables and class variables are encapsulated and
effectively private and constants are effectively public.
22. Subclassing and Inheritence
• When a class is defined it may extend or inherit from another class,
known as the superclass.
• If super class is not specified, then the class implicitly extends from
Object class.
• A class can have any number of subclass and every class has a single
superclass.
• The ancestors of a class are the superclass, plus the superclass of
the superclass and so on upto Object.
• The syntax for extending the class is simple, just add < character
and name of the superclass to your class statement.
class Point3D < Point
end
23. Contd..
Inheriting Methods
• The Point3D class we have defined is a trival subclass of
Poin. It declares itself an extension of Point, but there is no
class body.
p2 = Point.new(1,2)
p3 = Point3D.new(1,2)
print p2.to_s, p2.class # prints “(1,2) Point”
print p3.to_s, p3.class # prints “(1,2) Point3D”
• So the Point3D as inherited initialize and to_s method from
Point class.
24. Contd..
Overriding Methods
• We can customize the inherited behavior of the class by redefining
inherited methods.
• For example, the Object class defines a to_s method to convert an object
to a string in a very generic way. This was redefined in Point class to
override this method inherited from Object.
• When method is invoked, they are looked up dynamically so that the
appropriate definition or redefinition of the method is found. This method
look up happens at the time of execution.
• Private methods cannot be invoked from outside the class that defines
them. But they are inherited by subclass.
• So the private methods can be invoked from subclass and can override
them.
• Class methods may be inherited and overridden just as instance methods
can be.
25. Contd..
Augmenting Behavior by Chaining
• Sometimes when we override a method, we don’t want to replace it altogether,
we just want to augment the behavior by just adding new code.
• To do this we need to invoke the overridden method from the overriding method,
this is known as chaining.
• This is accomplished with the keyword super.
• Super invokes a method with the same name as the current one, in the superclass
of the current class.
• Specifying arguments for super just as for a normal method invocation.
class Point3D < Point
def initialize(x,y,z)
super(x,y)
@z = z
end
end
• If super is used as bare keyword, then all the arguments that were passed to the
current method are passed to the superclass method.
• Class methods can also use super just as an instance methods to invoke the same
named class method in the superclass.
26. Contd..
Inheritance and Variables
Instance Variables
• Instance variable often appear to be inherited in Ruby.
class Point3D < Point
def initialize(x,y,z)
super(x,y)
@z = z
end
def to_s
“#{@x, @y, @z}” # Variables @x and @y are inherited?
end
end
• But @x and @y are not inherited, Because instance variables are not defined by a
class they are unrelated to subclassing and the inheritance mechanism.
• Then chained method assigns the values to the variables @x and @y, which makes
those variables come into existence for a particular instance of Point3D.
• If a subclass uses an instance variable with the same name as a variable used by
one of its ancestors, it will overwrite the value of its ancestors variable.
• Class instance variables are not inherited.
27. Contd..
Class Variables and Constants
• Class variables are shared by a class and all of its sub classes.
• The subclass will change the value of class variable if a value is
assigned to same class variable that is already in use.
• Constants are inherited and can be overridden, much like instance
methods can.
28. Object Creation and Initialization
new, allocate and initialize
• Every class inherits the class method new.
• new method has two jobs:
– It must allocate a new object-actually bring the object into existence.
– It must initialize the object.
• The new method were actually written then it would look like:
def new(*args)
o = self.allocate
o.initialize(*args)
o
end
• It will delegates these two jobs to the allocate and initialize methods.
• allocate is instance method of class and it is inherited by all class objects.
• initialize method is to create instance variables for the object and set
them to their initial values.
29. Contd..
dup, clone and initialize_copy
• Another way that new objects come into existence is as a result of the dup
and clone methods.
• These methods allocate a new instance of the class of the object on which
they are invoked and copies all the instance variables to the newly
allocated object.
• The clone takes one step further by copying all singleton methods of the
receiver object and freezes the object if original is frozen.
• If a class defines initialize_copy method then clone and dup will invoke
that method on the copied object after copying the instance variable from
the original.
• clone calls the initialize_copy method before freezing the object. This
method is always private.
• Technique to prevent copying of objects is to use undef to simply remove
the clone and dup methods.
30. Contd..
Singleton Pattern
• A singleton is a class that has only a single instance.
• Singleton can be used to store the global program state within an
object-oriented framework.
• The new and allocate methods must be made private, dup and
clone must be prevented from making copies.
• The Singleton module in the standard library does this work for us
by “require ‘singleton’” and then “include Singleton” into your
program class.
• This defines a class method named instance, which takes no
arguments and returns the single instance of the class.
• Define an initialize method to perform initialization of the single
instance of the class.
31. Contd..
require 'singleton' # Singleton module is not built-in
class PointStats # Define a class
include Singleton # Make it a singleton
def initialize # A normal initialization method
@n, @totalX, @totalY = 0, 0.0, 0.0
end
def record(point) # Record a new point
@n += 1
@totalX += point.x
@totalY += point.y
end
def report # Report point statistics
puts "Number of points created: #@n"
puts "Average X coordinate: #{@totalX/@n}"
puts "Average Y coordinate: #{@totalY/@n}"
end
end
32. Contd..
• With a class like this in place, we might write the initialize method
for our Point class like this:
def initialize(x,y)
@x,@y = x,y
PointStats.instance.record(self)
End
• The Singleton module automatically creates the instance class
method for us, and we invoke the regular instance method record
on that singleton instance. Similarly, when we want to query the
point statistics, we write:
PointStats.instance.report
33. Modules
• Modules are a named group of methods, constants, and class
variables.
• Modules are defined much like classes are, but the module keyword
is used in place of class keyword.
• Modules cannot be instantiated and it cannot be subclassed.
• Modules are used as namespaces and as mixins.
• Just as class object is instance of the Class class, a module is
instance of Module class.
• Class is subclass of Module.
34. Contd..
Modules as Namespace
• Modules are a good way to group related methods when object-oriented
programming is not necessary.
• Module names must begin with a capital letter, just as class names do.
• Modules may also contain constants.
• Modules including classes, may be nested.
• This creates nested namespaces but has no other effect: a class or module
nested within another as no special access to the class or module it is
nested within.
Modules as Mixins
• If a module defines instance methods instead of class methods, those
instance methods can be mixed in to other classes.
• The best example for mixin is Enumerable and Comparable
35. Contd..
• To mix a module into a class use include keyword.
class Point
include Comparable
end
• Because include is a private method of Module it must be invoked
as a function.
• Include accepts any number of Module objects to mix in.
include Comparable, Enumerable
• The include method does not allow a class to be included within
another class. The arguments to the include should be modules
declared with module, not class.
• One module can be included into another. Doing so instance
methods from one module are included to another.
36. Loading and Requiring Modules
• Ruby programs may be broken up into multiple files.
• The most natural way to partition a program is to place each nontrivial
class or module into a separate file.
• These separate files can be reassembled into a single program by using
require and load.
• These are global functions defined in Kernel, but are used like language
keyword.
• The load and require method is also used for loading files from the
secondary library.
• Require is much more commonly used then load.
• The file to be loaded is specified with an absolute path or is relative path
(~).
37. contd..
Require Load
1. Require usually passed with
library name with no extensions
2. It will prevent multiple loads of
same file.
3. It will keep track of loaded files
in a global array $”
1. Load expects complete file name
with extensions.
2. It will load the same file multiple
times.
3. It will not keep track of loaded
files.
The difference between load and require is as follows
• The load path is an array that you can access using either of the global
variables $LOAD_PATH or $:.
• Each element in the array are searched for files to be loaded.
38. Singleton Methods
• Methods that are defined for only a single object rather than a class
of objects.
• The singleton methods of an object are instance methods for the
anonymous metaclass.
39. Method Lookup
• When Ruby evaluates a method invocation expression, it must first figure out
which method is to be invoked. The process of doing this is called method lookup
or method name resolution.
• For method name invocation expression o.m, Ruby performs name resolution with
the following steps:
– First, it checks the metaclass of o for singleton methods named m.
– If not found, Ruby searches the class of object o for instance method named
m.
– If not found, Ruby searches the instance methods of any modules included by
the class of o. It searches in the reverse order of the included modules.
– If not found, then the search moves up to the inheritance hierarchy to the
superclass.
– If no method is found named m, then a method name method_missing
is invoked instead.