Anidar clases

JSimpleClass permite anidar clases, las clases anidadas pueden ser públicas, privadas, estáticas.


function ClassA(){
	//public class
	this.PublicClass = Class.create(this.$$className + "::public.PublicClass",function(){
		var value = "[public]";
		this.getValue = function(){
			return value;
		};
		this.$$constructor = function(){};
	});
	//private class
	var PrivateClass = Class.create(this.$$className + "::private.PrivateClass",function(){
		var value = "[private]";
		this.getValue = function(){
			return value;
		};
		this.$$constructor = function(){};
	});
	this.getInstancePrivateClass = function(){
		return new PrivateClass();
	};
	this.$$DEFINE_STATIC = function(){
		// public static class
		this.$$static.PublicStaticClass = Class.create(this.$$className + "::public::static.PublicStaticClass",function(){
				var value = "[public static]";
				this.getValue = function(){
					return value;
				};			
				this.$$constructor = function(){};
		});
	};
	this.$$constructor = function(){};
};

var ClassA = Class.create("ClassA",ClassA);

var instA = new ClassA();
alert(instA.getInstancePrivateClass().getValue());// [private]

var instA_public =  new instA.PublicClass();
alert(instA_public.getValue());// [public]

var instA_static = new ClassA.$$static.PublicStaticClass();
alert(instA_static.getValue());//[public static]

alert(Class.getDeclaredClasses(ClassA).reverse().join("\n"));
/*
	ClassA::public.PublicClass
	ClassA::private.PrivateClass
	ClassA::public::static.PublicStaticClass
 */ 


Para poder registrar los nombres de las clases anidadas, hemos utilizado $$className, más un string con la siguiente sintaxis, "::" + " private | public | static" + "." + "nombre de la clase".
Podemos crear subclases de ClassA y de las clases anidas públicas.


function ClassA(){
	//public class
	this.PublicClass= Class.create(this.$$className + "::public.ClassAB",function(){
		var value = "[public]";
		this.getValue = function(){
			return value;
		};
		this.$$constructor = function(){};
	});
	//private class
	var PrivateClass = Class.create(this.$$className + "::private.PrivateClass",function(){
		var value = "[private]";
		this.getValue = function(){
			return value;
		};
		this.$$constructor = function(){};
	});
	this.getInstancePrivateClass = function(){
		return new PrivateClass();
	};
	this.$$DEFINE_STATIC = function(){
		//public static class
		this.$$static.PublicStaticClass = Class.create(this.$$className + "::public::static.ClassAD",function(){
			var value = "[public static]";
			this.getValue = function(){
				return value;
			};			
			this.$$constructor = function(){};
		});
	};
	this.$$constructor = function(){};

};

var ClassA = Class.create("ClassA",ClassA);

var ClassB = Class.extend("ClassB",ClassA,function(){

	//public class
	this.PublicClass = Class.extend(this.$$className + "::public.PublicClass",this.PublicClass,function(){
		
		this.getValue = function(){
			return  this.$$super[0].getValue() + " [override "+ this.$$className + "]";
		};
		this.$$constructor = function(){};
	});

	this.$$DEFINE_STATIC = function(){
		//public static class
		this.$$static.PublicStaticClass = Class.extend(this.$$className + "::public::static.ClassAD",
			this.$$static.PublicStaticClass, function(){
			this.getValue = function(){
				return  this.$$super[0].getValue() + " [override " + this.$$className + "]";
			};			
			this.$$constructor = function(){};
		});
	};		

	this.$$constructor = function(){};
});
// clonamos la clase ClassB, la clase resultante será hermana.
var ClassC = Class.clone("ClassC",ClassB);

var instC = new ClassC();
alert(instC.getInstancePrivateClass().getValue());//[private]

var instC_public =  new instC.PublicClass();
alert(instC_public.getValue());//[public][ override ClassC::public.PublicClass]

var instC_static = new ClassC.$$static.PublicStaticClass();
alert(instC_static.getValue());//[public static][override ClassC::public::static.PublicClass]

alert(Class.getDeclaredClasses(ClassA).reverse().join("\n"));
 /*
	ClassA::public.PublicClass
	ClassA::private.PrivateClass
	ClassA::public::static.PublicStaticClass 
 */ 
 
 alert(Class.getDeclaredClasses(ClassB).reverse().join("\n"));
/*
	ClassB::public.PublicClass
	ClassB::public::static.PublicStaticClass 	
*/
 alert(Class.getDeclaredClasses(ClassC).reverse().join("\n"));
/*
	ClassC::public.PublicClass
	ClassC::public::static.PublicStaticClass 
*/

En el ejemplo podemos ver que es posible clonar una clase, para clonar una clase debemos utilizar los métodos y atributos de JSimpleClass para hacer referencia a las clase o superclases, por ejemplo, si en vez de utilizar $$className, hubiera puesto un string con el nombre de ClassB, Class.getDeclaredClasses(ClassC) devolvería el mismo resultado que Class.getDeclaredClasses(ClassB).

Cuando declaramos una clase estática anidada, al crear una subclase de la clase contenedora, JSimpleClass creara otra vez la clase estática anidada, este comportamiento hará que los atributos estáticos tomen los valores que declarado al inicio y getDeclaredClasses no devuelva el nombre de la clase dónde fue declarada sino el de la subclase.
Podemos verlo en el siguiente ejemplo:


function ClassA(){

	this.PublicClass = Class.create(this.$$className + "::public.PublicClass",function(){
		var value = "[public]";
		this.getValue = function(){
			return value;
		};
		this.$$constructor = function(){};
	});	
	
	this.$$DEFINE_STATIC = function(){
		//public static class
		this.$$static.PublicStaticClass = Class.create(this.$$className + "::public::static.PublicStaticClass",function(){
			this.$$DEFINE_STATIC = function(){
				this.$$static.instances = [];	
			};
			this.$$constructor = function(){};
		});
	};
	
	this.$$constructor = function(){
		this.$$static.PublicStaticClass.$$static.instances.push(this);
	};
 };
 
var ClassA = Class.create("ClassA",ClassA);

var ClassB = Class.extend("ClassB",ClassA,function(){

	this.$$constructor = this.$$super[0].$$constructor;
});


var instA1 = new ClassA();
var instA2 = new ClassA();

alert(ClassA.$$static.PublicStaticClass.$$static.instances.length);// 2
alert(ClassB.$$static.PublicStaticClass.$$static.instances.length);// 0

alert(Class.getDeclaredClasses(ClassB).reverse().join("\n"));
/*
	ClassA::public.PublicClass
	ClassB::public::static.PublicStaticClass
*/

Si este comportamiento no es el que buscamos tenemos que utilizar $$super.


function ClassA(){

	this.PublicClass = Class.create(this.$$className + "::public.PublicClass",function(){
		var value = "[public]";
		this.getValue = function(){
			return value;
		};
		this.$$constructor = function(){};
	});	
	
	this.$$DEFINE_STATIC = function(){
		//public static class
		this.$$static.PublicStaticClass = Class.create(this.$$className + "::public::static.PublicStaticClass",function(){
			this.$$DEFINE_STATIC = function(){
				this.$$static.instances = [];	
			};
			this.$$constructor = function(){};
		});
	};
	
	this.$$constructor = function(){
		this.$$static.PublicStaticClass.$$static.instances.push(this);
	};
 };
 
var ClassA = Class.create("ClassA",ClassA);

var ClassB = Class.extend("ClassB",ClassA,function(){
	
	this.$$DEFINE_STATIC =  function(){
		this.$$static.PublicStaticClass = this.$$super[0].$$static.PublicStaticClass; 
	};
	this.$$constructor = this.$$super[0].$$constructor;
});


var instA1 = new ClassA();
var instA2 = new ClassA();

alert(ClassA.$$static.PublicStaticClass.$$static.instances.length);// 2
alert(ClassB.$$static.PublicStaticClass.$$static.instances.length);// 2

alert(Class.getDeclaredClasses(ClassB).reverse().join("\n"));
/*
	ClassA::public.PublicClass
	ClassA::public::static.PublicStaticClass
*/


El trabajo con clases anidadas puede ser muy enrevesado y puede complicar el seguimiento del código, pero puede ser útil en algunos contextos.