Nullオブジェクト

30分プログラム、その158。Nullオブジェクトを作る。

RubyのNilClassは無関係で、デザインパターンのほうのNullオブジェクト。適当に要約すると、処理Aをするクラスと、処理Bをするクラスと、何もしないクラスを用意して、それぞれ状況に応じて別のクラスに渡すようにすると、処理をする場合と処理をしない場合をわける必要がなるなる、というパターン。

で、このNullオブジェクトを簡単につくるためのクラスを定義してみる。
最初は、いかなるメソッドが呼ばれてもエラーにならないクラスを定義してみた。でも、これだとメソッド名を間違えても文句を言わなくて困るので、指定したメソッドだけ処理するクラスも定義した。

使い方

irb> require 'nullobject'

# eaterに何を食べさせても、エラーにならない
irb> eater = Eater.new
=> #<Eater:0x10a12b0>
irb> eater.f
=> nil
irb> eater.b
=> nil
irb> eater.g
=> nil


# fとgだけを受けつけるFooを作成
irb> Foo = NullObject.new :f,:g
=> Foo
irb> foo = Foo.new
=> #<Foo:0x108bbb8>
irb> foo.f
=> nil
irb> foo.g 1,2,3
=> nil

# fとg意外を食べさせると、エラーを吐く
irb> foo.h
NoMethodError: undefined method `h' for #<Foo:0x108bbb8>
        from (irb):11

ソースコード

#! /opt/local/bin/ruby -w
# -*- mode:ruby; coding:utf-8 -*-
#
# nullobject.rb -
#
# Copyright(C) 2007 by mzp
# Author: MIZUNO Hiroki <hiroki1124@gmail.com> 
# http://mzp.sakura.ne.jp/
#
# Timestamp: 2007/10/17 23:13:09
#
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Ruby itself.
#
class Eater
  def method_missing(*_);  end
end

class NullObject
  def self.new(*methods)
    klass = Class.new
    klass.module_eval{
      methods.each{|name|
        define_method(name){|*args|
        }
      }
    }
    klass
  end
end

if $0 == __FILE__ then
  NullFoo = NullObject.new :bar,:baz
  foo = NullFoo.new
  foo.bar
  foo.baz 1,2,3
end