Null Objects

Tom Locke and I have similar proclivities. He says:


class Object
  def _?()
    self
  end
end

class NilClass
  def _?()
    SafeNil.new
  end
end

class SafeNil
  def method_missing(*args, &b)
    nil.send(*args, &b) rescue nil
  end
end

I say:


class Object
  def null
    n = nil
    def n.method_missing(*args)
      null
    end
    n
  end
end

The difference:


string_or_nil._?.length        # Tom's
(string_or_nil||null).length   # mine

I like being able to go more than one method deep,


(string_or_nil||null).length * 4

But that might not be to your taste.

4 Comments

Tom LockeAugust 25th, 2007 at 10:31 am

Nice. Is your line 4 supposed to read:

def n.method_missing(*args)

?

DanielAugust 25th, 2007 at 10:42 am

Yes thanks, fixed now. Also instead of Object.new the singleton object needed to be nil, to evaluate as false. Should have checked before typing.

Tyler RickOctober 12th, 2007 at 1:27 am

I like how simple your implementation is compared to Tom’s.

Unfortunately, I believe it has a fatal flaw: As soon as you call null once, the NilClass is permanently changed and *all* nil objects will have this new “safe nil” behavior.

puts nil.foo rescue p $!
# => #

null

puts nil.foo rescue p $!
# => nil

I don’t really understand why it has to be this way, but I’m guessing it has to do with the fact that nil itself is a “singleton object” (according to http://corelib.rubyonrails.org/classes/NilClass.html)

DanielOctober 23rd, 2007 at 3:38 am

Ah. I was wondering how long it would take you to work that out. :)
(http://www.imdb.com/title/tt0062552/quotes)

Let this be a lesson in how to shoot yourself in the foot with open core classes. Maybe I should be using Java so I don’t hurt myself.

Leave a comment

Your comment