Search code examples
rubytruthiness

How to inherit from NilClass or how to simulate similar function


I just want to use Null Object Design Pattern, but I found I can inherit from NilClass.

I can write a method "nil?" and return false but what if user write code below

if null_object 
  puts "shouldn't be here"
end

For clarify what I try to do is:

record = DB.find(1)
# if it can not find record 1, the bellow code should not raise exception
record.one_attr 
# and what's more
if record 
  puts "shouldn't be here"
end
# I don't want to override all NilClass

Solution

  • An approach that may work for you is to overide the method #nil? in your Null object. This means that in your code to test for null you have to use obj.nil? and not just check for obj existence. This is probably reasonable, since you can distinguish between nil and null. Below is an example:

    class NullClass
      def nil?
        true
      end
    
      def null_behavior
        puts "Hello from null land"
      end
    end
    

    Inheritance will work:

    class NewClass < NullClass
    end
    

    Use like so:

    normal = Class.new
    null = NewClass.new
    
    x = [normal, null]
    
    x.each do |obj|
      if obj.nil?
        puts "obj is nil"
        obj.null_behavior
      end
    end
    

    Output:

    obj is nil
    Hello from null land
    

    Just remember to use #.nil? for any checks that require Null and Nil to be false-ish.

    Below this line was my WRONG initial answer

    CustomNil = Class.new(NilClass) 
    
    class CustomNil
      def self.new
        ###!!! This returns regular nil, not anything special.
      end
    end
    

    [tests deleted for brevity]

    Use at your own risk. I haven't researched what side effects this may cause or whether it will do what you want. But it seems it does have some nil like behavior