# Useful uses for instance-specific methods

**URL:** <https://www.ruby-forum.com/t/useful-uses-for-instance-specific-methods/129480>\
**Category:** Ruby\
**Created:** [February 18, 2008, 11:10pm UTC](https://www.ruby-forum.com/t/useful-uses-for-instance-specific-methods/129480 "2008-02-18T23:10:53Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [February 18, 2008, 11:10pm UTC](https://www.ruby-forum.com/t/useful-uses-for-instance-specific-methods/129480/1 "2008-02-18T23:10:53Z")

</div>

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.
