Pooh program example 10-object-closure-point.p
# Object oriented programming with closures: point class
sub makepoint( x, y )
# the object state here are the constructor arguments (x, y)
# very similar to object by closure
# an advantage of object-by closure over object as hash (ala javascript)
# when you type the code, the instance method has to be defined as local of enclosing scope;
# so you can't misspell the member names.
# return factory method that returns object methods - both factory and object methods get capture of the object state
return sub( method )
if method eq 'move'
return sub( dx, dy )
outer . x = outer . x + dx
outer . y = outer . y + dy
end
elsif method eq 'print'
return sub()
println( ~msg 'position x = [ outer.x ] y = [ outer.y ]' )
end
elsif method eq 'x-pos'
return sub()
return outer.x
end
elsif method eq 'y-pos'
return sub()
return outer . y
end
end
end
end
# make point object
point := makepoint( ~x 42 ~y 10 )
# show position of point
point( ~method 'print') ()
point( ~method 'move') ( ~dx 10 ~dy 10 )
# show position of point after having moved it.
point( ~method 'print') ()
# call accessor methods.
println( ~msg 'horizontal postion [ point( ~method 'x-pos') () ] vertical position [ point( ~method 'y-pos') () ]' )
position x = 42 y = 10 position x = 52 y = 20 horizontal postion 52 vertical position 20Trace output for 10-object-closure-point.p
039|... := makepoint( ~x 42 ~y 10 )... 014| return sub (~method) 039|point := makepoint( ~x 42 ~y 10 ):-> sub 042|point:-> sub ( ~method 'print' )... 015| if (method:'print' eq 'move'):false 020| else if (method:'print' eq 'print'):true 021| return sub () 031| end # if 042|point:-> sub ( ~method 'print' ):-> sub ( )... 022| println( ~msg 'position x = ' .. outer.x:42 .. ' y = ' .. outer.y:10 .. '' )... 044|point:-> sub ( ~method 'move' )... 015| if (method:'move' eq 'move'):true 016| return sub (~dx , ~dy) 019| end # if 044|point:-> sub ( ~method 'move' ):-> sub ( ~dx 10 ~dy 10 )... 017| outer.x = (outer.x:42 + dx:10):52 018| outer.y = (outer.y:10 + dy:10):20 047|point:-> sub ( ~method 'print' )... 015| if (method:'print' eq 'move'):false 020| else if (method:'print' eq 'print'):true 021| return sub () 031| end # if 047|point:-> sub ( ~method 'print' ):-> sub ( )... 022| println( ~msg 'position x = ' .. outer.x:52 .. ' y = ' .. outer.y:20 .. '' )... 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' )... 015| if (method:'x-pos' eq 'move'):false 020| else if (method:'x-pos' eq 'print'):false 024| else if (method:'x-pos' eq 'x-pos'):true 025| return sub () 031| end # if 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( )... 026| return outer.x:52 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( ):52 .. ' vertical position ' .. point:-> sub ( ~method 'y-pos' )... 015| if (method:'y-pos' eq 'move'):false 020| else if (method:'y-pos' eq 'print'):false 024| else if (method:'y-pos' eq 'x-pos'):false 028| else if (method:'y-pos' eq 'y-pos'):true 029| return sub () 031| end # if 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( ):52 .. ' vertical position ' .. point:-> sub ( ~method 'y-pos' ):-> sub ( )... 030| return outer.y:20 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( ):52 .. ' vertical position ' .. point:-> sub ( ~method 'y-pos' ):-> sub ( ):20 .. '' )...