引数によって生成するインスタンスを変更する

配列arrayが中に入っているオブジェクトObj。Obj#[]で返される配列の要素をオブジェクトElemで包んで返す場合を考えてみる。

class Obj
  def initialize(array)
    @array = array
  end
  
  def [](i)
    Elem.new(@array[i])
  end
end

class Elem
  def initialize(elm)
    @elm = elm
  end
  
  def to_s
    @elm.to_s
  end
end

ここでarrayの要素にnilがあると、当然ながら

Elem.new(nil).nil? # => false

となる。こうではなく、nilが与えられたらnilを返すようにしたい。

ガードクラス(?)を用意する

ElemOrNilクラスを用意して、引数がnilの場合はnilを、それ以外の場合はElem.newを呼ぶようにする。

class Obj
  def initialize(array)
    @array = array
  end
  
  def [](i)
    ElemOrNil.new(@array[i])
  end
end

class ElemOrNil
  def self.new(elm)
    return nil if elm.nil?
    Elem.new(elm)
  end
end

class Elem
  def initialize(elm)
    @elm = elm
  end
  
  def to_s
    @elm.to_s
  end
end

こうすると、

ElemOrNil.new(nil).nil? # => true

となる。

同様の振り分けは可能

もちろんnilだけではなく、case文などで振り分ければいろいろなインスタンスを生成できると思います。