Friday, November 22, 2013

Whats there in an Object

Whats there in an Object


Lets start with the basics and look at the following piece of Ruby code:

 class A  
  def method  
   @v = 1  
  end  
 end  
 a = A.new  
 a.class # => A  

1) Instance Variables:

Objects contain instance variables, Ruby provides a method Object#instance_variables() to peek at them.

In the above example we have just one instance variable

 a.method  
 a.instance_variables # => [:@v]  

Unlike in static languages like Java, in Ruby there is no connection between an object's class and its instance variables.

Instance Variables come into existence whenever you assign them a value. Important thing to understand is that you can have objects of the "same" class that carry different sets of instance variables


Lets look at the following example:

 class A  
   def method  
     @v = 1  
   end  
   def new_method  
     @c = 2  
   end  
 end  
 a = A.new  
 a.method  
 a.instance_variables #=> [:@v]  
 b = A.new  
 b.new_method  
 b.instance_variables #=> [:@c]  


So if we hadn't called a.method() or b.new_method() objects a or b would not have any instance variables.


2) Methods

Besides having instance variables objects have methods

You can see an objects methods by calling Object#methods(). Most of the methods will be the methods inherited from Object so this list of methods will be quite long.

We can use Array#grep() to find the method we are looking for

 a.methods.grep(/new_/) #=> [:new_method]   


3) Classes: Yes, classes are nothing but objects in ruby and since a class is an object, everything that applies to an object also applies to a class.

Classes like any object have their own class, called Class

"hello".class # => String

The method of an object are the instance methods of its class. 
Methods of a class are the instance methods methods of Class.

Tuesday, October 1, 2013


MetaProgramming using Ruby


The Object Model:

See any ruby program and you will see objects everywhere. It includes language constructs such as classes, modules, variables, instance variables , class variables, methods etc. All these constructs together make the object model each playing some role. 

With the help of object model we are able to associate objects to classes or methods to classes and many many such questions. So lets dive into the first concept of metaprogramming using Ruby.

1) Open Classes:

Monkeypatching is not adviced.

 class String  
      def wow  
           "This is amazing ain't it"  
      end  
 end  


We opened the String class and we plant the wow method there which returns the text "This is amazing ain't it"

Once you do this, every string in the system will be exposed to the wow method.

Similarly you can open any class and add methods to it and it will be available to all the instances of that class.

The example above doesn't really make sense here but it shows the power of ruby wherein you can open any class and add methods to it as you desire

2) Inside Class definitions:

 3.times do   
      class C  
           puts "Wow"  
      end  
 end  

In Ruby there is no real distinction between code that defines a class and code of any other kind.
You can put any code you want in a class definition.

Above code will execute the code inside do...end block will be executed thrice but does that mean it defines class C three times?


Lets see another example:
 Class Amit  
   def first  
     puts "Amit"  
   end  
 end  
 Class Amit   
   def second  
     puts "Acharya"  
   end  
 end  
 a = Amit.new  
 a.first  #=>  "Amit"  
 a.second #=>  "Acharya"  


When the class Amit comes into the picture for the first time, no class by that name exists yet. So, Ruby steps in and defines the class and the first method with it.

In the second Definition of class Amit, the Class already exists, so Ruby doesn't need to define the class again, As learned earlier, it uses Open Classes concept to open the method and define the second method insice class Amit.

The core job of the class keyword is to give you the context of the class where you can define methods.

3) Real life example of Open Class

You can convert any number to Money object by calling Numeric#to_money()

amount = 100.to_money()

so to_money methods has to be defined in the Numeric class (100's class)

Following is the snippet from the money gem where in it opens the Numeric Class and adds the to_money method, similary you can find the same in the String class so you can do "100".to_money()


1:  # Open +Numeric+ to add new method.  
2:  class Numeric  
3:   # Converts this numeric into a +Money+ object in the given +currency+.  
4:   #  
5:   # @param [Currency, String, Symbol] currency  
6:   #  The currency to set the resulting +Money+ object to.  
7:   #  
8:   # @return [Money]  
9:   #  
10:   # @example  
11:   #  100.to_money          #=> #<Money @cents=10000>  
12:   #  100.37.to_money        #=> #<Money @cents=10037>  
13:   #  BigDecimal.new('100').to_money #=> #<Money @cents=10000>  
14:   #  
15:   # @see Money.from_numeric  
16:   #  
17:   def to_money(currency = nil)  
18:    Money.from_numeric(self, currency || Money.default_currency)  
19:   end  
20:  end  

4) Problem with Open Classes
It is very easy to accidentally overwrite an existing method definition and that could cause nasty bugs,
e.g. if you replace the String#length() with your own version of length(), that could cause unwanted bugs in the system.