Febrero 11, 2004

Accediendo a las propiedades de una clase de forma dinámica

Es probable que esto no suponga niguna novedad, pero de todas formas, vamos allá:

Actualmente estoy trabajando en una clase para serializar y deserializar otras clases. Por ejemplo, la siguiente:

class net.designnation.tests.Serializable
{
 	private var prop1: String;
 	private var prop2: Number;
 	private var prop3: Object;
 	
 	private var unseen: String;
 	
 	public static var CONSTANT: String = "Esto es una constante";
 	
 	function Serializable( )
 	{	
  		this.unseen = "Hola, mundo!";
  	}
 	
 	public function set val1( param: String )
 	{
  		this.prop1 = param + " <:::::::: setter ";
  	}
 	
 	public function get val1( ): String
 	{
  		return this.prop1 + " <:::::::: getter ";;
  	}
 	
 	public function set val2( param: Number )
 	{
  		this.prop2 = param + 100;
  	}
 	
 	public function get val2( ): Number
 	{
  		return this.prop2 + 10000;
  	}
 	
 	public function set val3( param: Object )
 	{
  		this.prop3 = param;
  	}
 	
 	public function get val3( ): Object
 	{
  		return this.prop3;
  	}
}

Para leer sus propiedades, podemos hacer lo siguiente:

import net.designnation.tests.*
import net.designnation.utils.*

var myClass: Serializable = new Serializable( );

myClass.val1 = "Hi!";
myClass.val2 = 32;
myClass.val3 = { prop: "value" };

trace(" ------------------------\n ");
for ( var k in myClass )
{
 	trace( k + " == " + myClass[ k ] );
}

//setting

for ( var k in myClass )
{
 	if ( k == "prop1" ) myClass[ k ] = "modificado";
 	if ( k == "unseen" ) myClass[ k ] = "unseen, modificado";
}
//checking

trace(" \n------------------------\n ");
for ( var k in myClass )
{
 	trace( k + " == " + myClass[ k ] );
}

Pero, qué ocurre cuando queremos acceder a esas propiedades a través de sus getters / setters?. Pues que no lo podemos hacer, ya que no aparecen en el bucle for .. in

Pero, utilizando ASSetPropFlags, se pueden mostrar todas las propiedades y métodos de myClass.__proto__, es decir, de la clase a partir de la cual se instancia ese objeto. Esto es muy peligroso, porque realmente no se sabe durante cuánto tiempo va a seguir existiendo ese método. Pero, para nuestro caso, es la forma de poder acceder a todos los métodos de la clase

class net.designnation.utils.showProps
{
 	static function showAll( obj )
 	{
  		_global.ASSetPropFlags( obj.__proto__, null, 0, 1 );
  		return obj;
  	}
}

De vuelta al script:

// Mostrando todas las propiedades

myClass = showProps.showAll( myClass );

trace(" \n------------------------\n ");
for (var k in myClass)
{
 	trace( k );
}

//Obeteniendo los valores a través de los getters

trace( " \n------------------------\n " );
trace( " Llamando a los getters \n" );
for (var k in myClass)
{
 	var prefix: String = k.substring( 0, 7 );
 	var posfix: String = k.substring( 7, k.length);
 	
 	if ( prefix == "__get__" )
 	{
  		trace( myClass[ k ]( ) );
  	}
}

trace( " \n------------------------\n " );
trace( " seteando utilizando los setters \n" );
for (var k in myClass)
{
 	var prefix: String = k.substring( 0, 7 );
 	var posfix: String = k.substring( 7, k.length);
 	
 	if ( prefix == "__set__" )
 	{
  		if ( posfix == "val1" ) myClass[ k ]( " the end " );
  	}
}

trace( myClass.val1 );

Resuelto. Peligroso, no muy limpio, pero puede sacar de algún apuro.

Escrito por Cesar Tardaguila en: Febrero 11, 2004 10:45 PM | TrackBack
Comentarios