Saturday, 21 January 2012

Ruby Open Classes

Coming from the .NET world, if we ever wanted to improve a class (by adding to it's code), we really only had a couple of options:


This is limiting because .NET is a single-inheritence model. This means a class can only be subclassed once. So if other developers want to add more functionality, you can end in an inheritance chain nightmare.

Extension Methods

Since .NET 3.0, we've had extension methods. These allow you to bolt your own methods on to a type - the one gotcha being that they must be static. This would mean that you could only get at any public members of the instance you are executed against.

(I should note, these are not criticisms of the language. Just because I have jumped ship to Ruby, I still consider .NET to be a top-notch framework)

Enter "Open Classes"

In Ruby, we have what are called "Open Classes" - and they are pretty much what they say on the tin. Classes are open for extension and modification (yups, direct violation of the Open-Closed Principle).

Anyway, enough talk, let's see the code.

Example 1: Opening String

First up, let's simply add some nice functionality to String to see if it's a valid email address.

Lets get the a regex for a RFC2822-compliant email address.

Courtesy of [regexlib](
Even though this is of course very easy to remember, let's make it a little more readable:

No messing around, and makes for somewhat readable code. Moving on.

Example 2: Opening and using instance variables

What's cool, is that we can access all the instance variables in the class too - this means we can truly extend the class with little effort (and where it gets one over on extension methods).

Let's say we are using a piece of code from an OSS library that returns error codes from printing devices. We don't want to keep passing the return values around to retrieve the commonly used error message that accompanies it. However, these messages are business-specific, so don't belong in the OSS library.

The dark side of the force

As you can see, this is pretty powerful stuff, but as you know with great power comes great responsibility.

Not so good. Jay Fields has a great article on alternatives that may be useful if you find you need to tread on other peoples toes..

A lot of my fellow .NET developers are probably screaming at the monitor at this point "WHY BOTHER IF IT'S SO DANGEROUS" (I thought the same when I first saw it) but the truth is this - in the right hands (and I consider the developers I tend to frequent with far more talented than myself), it's a powerful and can a very useful feature*.

* Especially if you discover some weird bug that you need to patch before you can get it merged into the main code base.

No comments:

Post a Comment