Shining Ruby: Extending Classes

I’ve been playing with Ruby a little and there’s one feature in Ruby that I particularly like: the ability to extend existing classes. For example, for as long as I’ve been programming using objects I wanted to add a method to integers called “timesSayZef”. So you could do this:

100.timesSayZef()

And it would print “Zef” a hundred times. However, Java doesn’t allow you to do this, C# doesn’t allow you to do this, even Python doesn’t allow you to do this (at least I couldn’t get it to do it). However, Ruby does with this code:

class Fixnum
   def timesSayZef
      times { puts "Zef" }
   end
end

In Ruby when you define a class that already exists (such as Fixnum, which represents a number, such as 100), it will merge the two definitions. So in this case I would add a timesSayZef method to the Fixnum class. When I now do this:

10.timesSayZef
it will print:
Zef
Zef
Zef
Zef
Zef
Zef
Zef
Zef
Zef
Zef

Cool huh?

Ruby also allows you to extend existing objects with additional methods. For example:

class BoringClass
   def saySomething
      puts 'Something'
   end
end
module ZefStuff
   def sayZefIsCool
      puts 'Zef is cool!'
   end
end
bc = BoringClass.new
bc.saySomething
bc.extend(ZefStuff)
bc.sayZefIsCool

What I do here is first define a class. Then define a module. Create an instance of the class and then extend that instance with all the methods in the module. This example will print:

Something
Zef is cool!

View Comments

  1. Well.. I guess it would get pretty tricky surrounding performance and conformance.. also it would get tricky getting the type defenitions in some cases synchronised.

    I’d rather see ‘wrapper’ like abilities…

    So you’d define a class which ‘wraps’ another class and then you’ll be able to cast that existing class to that new wrapping class.

    Then you’d use something like:

    ((IZefTimeSayZefable)(100)).zefSayZef()

    Although dynamic languages could see that cast automaticly..

    although this makes me wonder whether ruby uses this kind of a wrapping already… :p

  2. Numbers are the only things in Python that are not objects (and the ruby people are quick to point that out).

    But you could do this: “Zef”*10 and I don’t know ruby well enough to copy the second code snippet but I’m sure it’s easy with decorators or metaclasses or something.

  3. It couldn’t totaly be I realised…

  4. 10 PRINT “Zef” 20 GOTO 10 RUN

  5. Rickard Andersson

    I agree with Zef. The ability to dynamically extend classes and objects is indeed one of the most admirable qualities of Ruby. If I’m not mistaken, Ruby on Rails utilizes this capability to a large degree.

    “But you could do this: “Zef”*10″

    There are of course other ways of printing Zef ten times, but that’s completely beside the point.

  6. yeah I know, but I had to point it out :P

  7. Dagur, numbers are objects in Python and have been for a long time (perhaps even from the very beginning). They’re just immutable so one can’t modify the number objects nor the number class. But custom objects could be made immutable as well and they wouldn’t be any less “objects”.

blog comments powered by Disqus