Useful uses for instance-specific methods

I ran into two specific cases this weekend where singleton methods
made my code feel a lot cleaner. For your enjoyment, I'll show them
both here.

Here's the first version of the code:

  class WordTreeNode
    attr_accessor :parent
    attr_accessor :text_value
    attr_accessor :source_value
    def initialize( text_value=nil )
      @children = []
      @text_value = text_value
    end
    def <<( kid )
      @children << kid
      kid.parent = self
    end
    def text
      @text_value || @children.map{ |kid| kid.text }.join
    end
    def source
      @source_value || (@parent && @parent.source)
    end
  end

  root = WordTreeNode.new
  root.source_value = "Bob"
  root << (greeting = WordTreeNode.new)
  root << (query = WordTreeNode.new)
  greeting << WordTreeNode.new( "Hi there! " )
  query << WordTreeNode.new( "What are you " )
  query << WordTreeNode.new( "doing tonight?" )

  p root.text
  #=> "Hi there! What are you doing tonight?"
  p query.source
  #=> "Bob"

Now, we clean it up a little bit to simplify the implementation of
#source and #text:
  class WordTreeNode
    attr_accessor :parent
    def initialize
      @children = []
    end
    def <<( kid )
      @children << kid
      kid.parent = self
    end
    def text
      @children.map{ |kid| kid.text }.join
    end
    def source
      @parent && @parent.source
    end
  end
  class RootNode < WordTreeNode
    attr_accessor :source
    def initialize( source )
      super()
      @source = source
    end
  end
  class LeafNode < WordTreeNode
    attr_accessor :text
    def initialize( text )
      super()
      @text = text
    end
  end

  root = RootNode.new( "Bob" )
  root << (greeting = WordTreeNode.new)
  root << (query = WordTreeNode.new)
  greeting << LeafNode.new( "Hi there! " )
  query << LeafNode.new( "What are you " )
  query << LeafNode.new( "doing tonight?" )

But we can also choose not to have those as separate classes:
  class WordTreeNode
    attr_accessor :parent
    def initialize
      @children = []
    end
    def <<( kid )
      @children << kid
      kid.parent = self
    end
    def text
      @children.map{ |kid| kid.text }.join
    end
    def source
      @parent && @parent.source
    end
    def self.leaf( text )
      node = self.new
      node.instance_eval{
        @text = text
        def text
          @text
        end
      }
      node
    end
  end

  root = WordTreeNode.new
  def root.source
    "Bob"
  end
  root << (greeting = WordTreeNode.new)
  root << (query = WordTreeNode.new)
  greeting << WordTreeNode.leaf( "Hi there! " )
  query << WordTreeNode.leaf( "What are you " )
  query << WordTreeNode.leaf( "doing tonight?" )

  p root.text
  #=> "Hi there! What are you doing tonight?"
  p query.source
  #=> "Bob"

The above code is less convoluted in Io, where I actually performed
this. (In Io you don't have to set a string value and then write a
method that returns that value...you simply set the "text" or "source"
message on the instance to *be* the string.) But hopefully it shows
you an interesting case where duck typing and per-instance-methods can
overlap to easily handle the edge cases.