30 Days of Tech: Day 21 - Object Literals
June 21st, 2008
You can do object oriented programming in both Ruby and Javascript. I think most people would agree that Ruby is “more” object oriented than Javascript, whatever subjective judgement they’re using. One thing that’s interesting to me, though, is that Javascript has a syntax for literal objects built in where as Ruby does not.
Javascript is prototype based, which means that every object that’s created actually just copied from another object. The object being copied is called the “prototype”, and forms a sort of factory for creating new objects. But then were do the prototype objects come from? If all objects are created from prototypes, shouldn’t the prototypes be created from other prototypes? Javascript sort of sidesteps this issue a bit—it’s only half prototype based. All objects in Javascript are really just hashes and Javascript has a syntax for writing hash literals. That means you can create an object in Javascript just by creating a hash and skip the whole prototype business.
var counter = {
count: 0,
increment: function() {this.count +=1},
decrement: function() {this.count -=1}
};
This is a perfectly good counter object in Javascript. If you wanted to create a similar object in Ruby, the most straightforward way would be simply to create a class.
class Counter
def initialize
@count = 0
end
def increment
@count += 1
end
def decrement
@count -= 1
end
end
counter = Counter.new
There’s nothing wrong with this implementation at all. Every so often, though, I run into a situation where I just want to roll an object with 1 or 2 methods inline rather that creating a class. The class usually ends up outside the method, at best, if not in a separate file. In general this is good separation, but if the code is very simple it is sometimes more clear to simply see it in the context of the method that needs it. There is a roundabout way of achieving this in Ruby.
counter = Object.new.instance_eval do
@count = 0
def increment
@count += 1
end
def decrement
@count -= 1
end
self
end
I don’t think this buys you very much. It’s not very intention revealing, which means a new person reading it may spend as long understanding why it’s written like this as they would looking at up a separate class. Wouldn’t it be nice if Ruby supported a syntax to clean this up at least a bit? Maybe something like
object counter
@count = 0
def increment
@count += 1
end
def decrement
@count -= 1
end
end
Well, we can’t quite make it there without extending the syntax, but we can make a reasonable facsimile.
def object(&block)
object = Object.new
object.instance_eval(&block)
object
end
counter = object do
@count = 0
def increment
@count += 1
end
def decrement
@count -= 1
end
end
If you find yourself working in a system that demands a lot of object literals for some reason, I’m sure you’ll want something of the sort. Also, if you’re working on such a system, I fear for your soul…
Sorry, comments are closed for this article.