// Demo using functional (style) programming to simulate object oriented programming.
// $Header: $

// "constructor":  initialize instance state and provide method dispatch table
function new_person( in_name, in_gender, in_father, in_mother)
	{
	var name, gender, father, mother

	// initialize "instance" data:
	//  ("curry" paramters from outermost function,
	//  freezing them on this instance)

	name = in_name
	gender = in_gender
	father = in_father
	mother = in_mother

	// emulate an object by making a function that returns other functions
	return function( method_name)
		{
		// provide "method table":

		return ( method_name === 'get_name') ?
			// return the simple name of this person
			function ()
				{ return name }
			: ( method_name === 'get_geneology') ?
			// return the lineage of this person
			function ()
				{
				// TODO:  support non-sexist/linear geneology  :-)
				return name +
					( ! father ?
						''
						: ', ' +
							( gender === 'F' ? 'daughter' : 'son') +
							' of ' + father( 'get_geneology')()
					)
				}  // ______
			: ( method_name === 'be_adopted_by') ?
			// return a new instance of "this" person with a new parent
			function ( new_father, new_mother)
				{
				return new_person( name, gender,
					new_father ? new_father : father,
					new_mother ? new_mother : mother)
				}  // ______
			: undefined
		}  // ______

	}  // ______

// subclass constructor:  mutant-is-a-person
function new_mutant( in_name, in_gender,
		in_power, in_alias, in_father, in_mother)
	{
	// emulate a subclass by again making a function
	//  that returns other functions, and reusing the base class.
	return function( method_name)
		{
		var base, power, alias

		// initialize super-class:
		base = new_person( in_name, in_gender, in_father, in_mother)

		// initialize "instance" data:

		power = in_power
		alias = in_alias

		// provide extended "method table":

		return ( method_name === 'get_power') ?
			// return the power of this mutant
			function ()
				{ return power }
			: ( method_name === 'get_alias') ?
			// return the "code name" of this mutant
			function ()
				{ return alias }
			// override original method as needed here:
			: ( method_name === 'be_adopted_by') ?
			// return a new instance of "this" person with a new parent
			function ( new_father, new_mother)
				{
				return new_mutant( in_name, in_gender, power, alias,
					new_father ? new_father : in_father,
					new_mother ? new_mother : in_mother)
				}  // ______
			// return inherited methods:
			: base( method_name)
		}  // ______

	}  // ______

// demo simple use of "objects"
function demo_simple()
	{
	var adam, eve, abel

	adam = new_person( 'Adam', 'M')
	eve = new_person( 'Eve', 'F')
	abel = new_person( 'Abel', 'M', adam, eve)
	alert( 'Created instance for ' + abel( 'get_geneology')() )
	}  // ______

// demo more complex use of "objects"
function demo_complex()
	{
	var orig, piedro

	orig = new_mutant( 'Piedro', 'M', 'Speed', 'Quicksilver')

	// OK, abuse "adoption" for discovery of family secrets  :-)
	piedro = orig( 'be_adopted_by')(
			new_mutant( 'Magnus', 'M', 'Magnetism', 'Magneto') )
	alert( 'Created instance for "' + piedro( 'get_geneology')() +
			'" AKA "' + piedro( 'get_alias')() +
			'", power: ' + piedro( 'get_power')() )
	}  // ______

// drive pseudo-object function:
function demo()
	{
	var adam, eve, abel, annie, daddy_warbucks,
			piedro

	adam = new_person( 'Adam', 'M')
	// alert( 'Created instance for ' + adam( 'get_name')() )

	eve = new_person( 'Eve', 'F')
	abel = new_person( 'Abel', 'M', adam, eve)
	// alert( 'Created instance for ' + abel( 'get_geneology')() )

	annie = new_person( 'Annie', 'F')
	// alert( 'Created instance for ' + annie( 'get_geneology')() )

	daddy_warbucks = new_person( 'Daddy Warbucks', 'M')
	annie = annie( 'be_adopted_by')( daddy_warbucks)
	// alert( 'Created instance for ' + annie( 'get_geneology')() )

	piedro = new_mutant( 'Piedro', 'M', 'Speed', 'Quicksilver')
	alert( 'Created instance for "' + piedro( 'get_geneology')() +
			'" AKA "' + piedro( 'get_alias')() +
			'", power: ' + piedro( 'get_power')() )

	// OK, abuse "adoption" for discovery of family secrets  :-)
	piedro = piedro( 'be_adopted_by')(
			new_mutant( 'Magnus', 'M', 'Magnetism', 'Magneto') )
	alert( 'Updated "' + piedro( 'get_geneology')() + '"')
	}  // ______

// vi: ts=4 sw=4
// *** EOF ***