Artículo Delphi 

09th Jul 2008

Algunas ventajas… (¡si eres capaz de recordarlas!) - Parte IV

Antes de comentar nada mas, me gustaría hacer una apreciación sobre la entrada anterior y compartirla con vosotros, sobre algo que quizás ha pasado desapercibido pero que creo que vale la pena comentar. El caso, es que formalmente el ejemplo anterior funciona o da el resultado esperado pero… y aquí viene el pero…

*Resulta un tanto extraño el uso de un parámetro var, que nos permite acceder a la referencia, dentro de un método de clase, que se supone, como dice la misma palabra, va a ser genérico e implícito a la clase y no a la referencia misma.

Alguno habrá comentado… ¡yo ya me había dado cuenta!

Yaaaa :-) ¡Yo también!. De hecho he estado buscando el comentario que hacen al respecto en la ayuda del entorno…

Un segundo que la encuentre…

As a general rule, operators should not modify their operands. Instead, return a new value, constructed by performing the operation on the parameters

Lo cual nos lleva a pensar que no todo lo que funciona siempre es estrictamente correcto… o por otro lado, que no todo lo que se dice es estrictamente cierto. Cada cual lo enfoque como bien crea… :-) Si algo buscan estas lineas que compartimos, no es precisamente ser formalmente correctas, sino crear un pequeño espacio para reflexionar, donde no exista ese miedo terrible a equivocarnos. Muchas veces me he preguntado a mi mismo, cuantas preguntas habrán quedado sin respuesta en los foros, solo porque mucha de la gente que puede responderlas tiene miedo a decir una tontería. Y si esos son muchos… todavía son muchos mas los que han dejado de preguntar algo, solo porque piensan que los demás van a suponer que su pregunta carece de interés. Así que, de alguna forma, la idea es animaros a preguntar, a levantar la mano, a participar… y a seguir manteniendo la curiosidad por aprender, sin convertir nuestro trabajo en una mera y monótona acción de repetir trozos de código aprendidos.

Ahora podemos seguir. Ya no se por donde ibamos… :-)

Sí. Hablábamos de los Registros.

Veamos otro ejemplo donde podemos usar el operador implícito y la suma. He tenido que modificar un poco el código anterior, y el resultado de su ejecución será una ventana como la imagen siguiente:

Resultado de la ejecución del código

Veamos en primer lugar la unidad donde hemos declarado la estructura Record.
En esta ocasión voy a omitir comentarios explicativos porque el código es bastante claro, pero yo en vuestro caso, fijaría mi atención al momento en que se produce la asignación implícita, y como en nuestra ventana de resultados no aparece el nombre de la tarifa (tf)…

unit uRegistros2;
	
interface
	
type
  TTarifaRecord = record
  private
    FNombreTarifa: String;
    FPrecio: Double;
    procedure SetNombreTarifa(const Value: String);
    procedure SetPrecio(const Value: Double);
  public
    class operator Add(t1, t2: TTarifaRecord): TTarifaRecord;
    class operator Explicit(ATarifa: TTarifaRecord): Double;
    class operator Implicit(APrecio: Double): TTarifaRecord;
    property Precio: Double read FPrecio write SetPrecio;
    property NombreTarifa: String read FNombreTarifa write SetNombreTarifa;
  end;
	
implementation
	
class operator TTarifaRecord.Implicit(APrecio: Double): TTarifaRecord;
begin
   Result.Precio:= APrecio;
end;
	
class operator TTarifaRecord.Explicit(ATarifa: TTarifaRecord): Double;
begin
  Result:= ATarifa.Precio
end;
	
class operator TTarifaRecord.Add(t1, t2: TTarifaRecord): TTarifaRecord;
begin
  Result.FPrecio:= t1.FPrecio + t2.FPrecio;
  Result.FNombreTarifa:= t1.FNombreTarifa + ‘+’ + t2.FNombreTarifa;
end;
	
procedure TTarifaRecord.SetNombreTarifa(const Value: String);
begin
  FNombreTarifa := Value;
end;
	
procedure TTarifaRecord.SetPrecio(const Value: Double);
begin
  FPrecio := Value;
end;
	
end.

Para ver en funcionamiento nuestro registro nos basta añadir un evento click a cualquier boton de nuestro formulario y encadenar unas lineas de código que usen los operadores.

procedure TForm1.Button1Click(Sender: TObject);
var
  c: Integer;
  t1: Double;
  tf, tf1: TTarifaRecord;   
	
  s: String;
begin
	
  tf.Precio:= 4;
  tf.NombreTarifa:= ‘Tarifa1′;
	
  tf1.Precio:= 3;
  tf1.NombreTarifa:= ‘Tarifa2′;
	
  c:= 5;
	
  tf:= c *  Double(tf);
	
   s:= tf.NombreTarifa + ‘ vale en un primer momento ‘ + FormatFloat(’0.00′, tf.Precio) + ‘.’ + #13#10;
	
   tf:= 5;
	
   t1:=  TTarifaRecord(8).Precio;
	
   tf:= t1 * tf.Precio;
	
   s:= s + ‘En un momento posterior vale ‘ + FormatFloat(’0.00′, tf.Precio)+ #13#10;
	
   tf:= tf + tf1;
	
   s:= s + ‘Si se suman ‘ + tf.NombreTarifa + ‘ el resultado es ‘ + FormatFloat(’0.00′, tf.Precio);
	
   ShowMessage(s);
	
end;
	

Y ya para acabar, he recogido un párrafo de la ayuda que nos comenta la diferencia entre clases y registros, que es lo suficientemente explicito y claro como para no ser necesario traducirlo

Though records can now share much of the functionality of classes, there are some important differences between classes and records.

Records do not support inheritance.
Records can contain variant parts; classes cannot.
Records are value types, so they are copied on assignment, passed by value, and allocated on the stack unless they are declared globally or explicitly allocated using the New and Dispose function. Classes are reference types, so they are not copied on assignment, they are passed by reference, and they are allocated on the heap.
Records allow operator overloading on the Win32 and .NET platforms; classes allow operator overloading only for .NET.
Records are constructed automatically, using a default no-argument constructor, but classes must be explicitly constructed. Because records have a default no-argument constructor, any user-defined record constructor must have one or more parameters.
Record types cannot have destructors.
Virtual methods (those specified with the virtual, dynamic, and message keywords) cannot be used in record types.
Unlike classes, record types on the Win32 platform cannot implement interfaces; however, records on the .NET platform can implement interfaces.

Sigo pensando, y no deja de ser una opinión, la mía, con la que no se tiene por qué estar de acuerdo, que no tiene demasiado sentido este giro o nueva funcionalidad de la estructura Record. Pero ya que está… pues eso… ¡hay que intentar sacar el máximo partido a estos recursos!

¡y la única forma es conocerlos y acostumbrarnos a su uso!

¡Que tengais un buen día!

Posted by Posted by Administrador under Filed under Delphi Comments No Comments »

Artículo Delphi Entrada Diario 

22nd Jun 2008

Algunas ventajas… (¡si eres capaz de recordarlas!) - Parte III

Recordando la entrada anterior, en la que me cuestionaba la oportunidad de haber dotado una estructura clásica de nuestra programación, como puede ser la del registro (Record), de aspectos que podían acercarla notablemente a las clases, me llevó a profundizar un tanto sobre los motivos y ciertamente, tras la lectura de uno de los capítulos del libro “Delphi 2007 Handbook” de Marco Cantú, encontré que se aludían básicamente motivos de rapidez en la ejecución del código, por la forma en que se gestiona el acceso y la carga de la memoria en ambas estructuras. Los registros tienen menor coste en su gestión. Una variable local de registro, por poner un ejemplo, se gestiona en memoria desde la pila, motivo suficiente para que su coste sea menor que el soportado por una instancia de una clase que se ubica en una dirección de memoria y se gestiona desde el sistema de memoria (Memory Manager).

El ejemplo que pone M. Cantú para comentar como se sobrescriben los operadores creo que es claro y sencillo. Creo incluso que es el utilizado por todos los escritores conocidos para comentar estos aspectos. ya que la clase TPunto se presta como anillo al dedo para operaciones como cálculos de distancia asimilados en operadores básicos, como la suma (+), por poner el mas generalizado.

Ya sabéis que yo siempre me complico la existencia y cuando vi que ya me habían cogido el ejemplo del punto, ¡mierda! -exclame lamentándome- ¡ahora cual voy a coger yo…! Supuso que tuviera que activar las pocas neuronas libres y sanas que me quedan para inventarme algo que me sirviera para explicar cualquiera de los operadores redefinidos. Así que os pido perdón de forma anticipada si el ejemplo no es demasiado bueno ni claro. Se me ocurrió que una estructura de registro pudiera guardar tres precios distintos, que pudieran ser utilizados para calcular un total. Lo típico para no estrujarme demasiado la cabeza: Total es igual a cantidad por precio… jejeje :-)

Y en este caso, hoy llevaba en mente comentar uno de los menos conocidos, que era el operador Explicito, que nos permite convertir un registro a un tipo definido previamente, mediante una conversión explicita. En el caso del ejemplo de Marco Cantú, convertía un registro TRecordPoint, en su formato de texto, mediante la conversión string(C) siendo C la estructura de registro mencionada. El resultado de la conversión era un mensaje en el que se escribían las coordenadas del punto.

En nuestro caso, la conversión nos permitirá acceder a los métodos de una clase… de forma que solo sea creada una instancia de la misma, inspirandome en el patrón singleton, salvando las diferencias de que esto es un ejemplo patatero y para ir por casa.

Veamos…

Podemos empezar definiendo los tres tipos de tarifa.

Tarifa = (fbasica, fDoble, fTriple);

y la estructura que va a utilizarla y que nos devolverá la instancia de la clase creada. Este array nos permitirá acceder a los objetos cuando deseemos liberar la memoria que han reservado.

 TArrayTarifa = Array[Tarifa] of TTarifa;

Ahora la estructura del registro…

  TTarifaRecord = record
  private
    ListaTarifas: TArrayTarifa;
  public
   class operator Explicit(var ATarifa: TTarifaRecord): TTarifaSimple;
   class operator Explicit(var ATarifa: TTarifaRecord): TTarifaDoble;
    class operator Explicit(var ATarifa: TTarifaRecord): TTarifaTriple;
    procedure Inicializar;
    procedure Eliminar;
  end;

A ver que se nos ocurre para el primer operador Explicit

class operator TTarifaRecord.Explicit(var ATarifa: TTarifaRecord): TTarifaSimple;
begin
    if ATarifa.ListaTarifas[fBasica] = Nil then begin
      Result:= TTarifaSimple.Create;
      Result.Precio:= PrecioBasico;
      Result.NombreTarifa:= ‘Tarifa básica’;
      ATarifa.ListaTarifas[fBasica]:= Result;
    end
    else
      Result:= TTarifaSimple(ATarifa.ListaTarifas[fBasica]);
end;

Fijaros que para que el código funcione correctamente, previamente debemos invocar el método inicializar que nos permite asignar a Nil la estructura interna del array, que debe albergar una referencia a la instancia creada. En este caso concreto y para que se vea que puede ser hecho de varias formas, he asignado manualmente cada uno de los elementos del array pero lo propio podría haber sido el uso de [for] para recorrer el array, mediante una variable local de tipo Tarifa que es una enumeración y por lo tanto puede ser definidos los valores minimo y máximo mediante funciones como High o Low. En el método Eliminar, por el contrario, utilizaremos una nueva funcionalidad propia de esta versión de Delphi, que es otra de las novedades, y que reside en el uso de [for __ in _____ do] para recorrer el array.

Veamos que hace Inicializar.

procedure TTarifaRecord.Inicializar;
begin
  ListaTarifas[fBasica]:= Nil;
  ListaTarifas[fDoble]:= Nil;
  ListaTarifas[fTriple]:= Nil;
end;

Y finalmente, podemos ver la novedad de su uso, en el método Eliminar.

procedure TTarifaRecord.Eliminar;
var
  Item: TTarifa;
begin
  for Item in ListaTarifas do begin
     if Assigned(Item) then begin
       Item.Free;
     end;
  end;
  Inicializar;
end;

Y ahora ya, solo nos queda inventarnos un ejemplo donde podamos combinar su uso y probar que funciona correctamente.

procedure TForm1.Button1Click(Sender: TObject);
var
  c: Integer;   //cantidad
  t1, t2, t3: Double;    //total
begin
  //inicializamos a nil el array
  tf.Inicializar;
	
   c:= 5;
	
   t1:= c * TTarifaSimple(tf).Precio;
   t2:= c * TTarifaDoble(tf).Precio;
   t3:= c * TTarifaTriple(tf).Precio;
	
   //visualizamos el primer momento
   Edit11.Text:= FormatFloat(’0.00′, t1);
   Edit21.Text:= FormatFloat(’0.00′, t2);
   Edit31.Text:= FormatFloat(’0.00′, t3);
	
   //vamos a por el segundo momento
   //asignamos los precios a cero en las tres tarifas
   TTarifaSimple(tf).Precio:= 0;
   TTarifaDoble(tf).Precio:= 0;
   TTarifaTriple(tf).Precio:= 0;
	
   t1:= c * TTarifaTriple(tf).Precio;
   t2:= c * TTarifaDoble(tf).Precio;
   t3:= c * TTarifaSimple(tf).Precio;
	
   //segundo momento deberia tomar valores 0 en las tres
   //dada la asignacion anterior
   Edit12.Text:= FormatFloat(’0.00′, t1);
   Edit22.Text:= FormatFloat(’0.00′, t2);
   Edit32.Text:= FormatFloat(’0.00′, t3);
	
   //y para finalizar comprobaremos el nombre de la tarifa…
   EditNombreTarifa1.Text:=  TTarifaSimple(tf).NombreTarifa;
   EditNombreTarifa2.Text:=  TTarifaDoble(tf).NombreTarifa;
   EditNombreTarifa3.Text:=  TTarifaTriple(tf).NombreTarifa;
	
   //aqui deberia eliminar los objetos creados
   tf.Eliminar;
end;

Respecto al uso de la construcción [for… in] podemos decir que se asimila al concepto de iterador que ya hemos usado anteriormente desde el código que hemos compartido (¿recordais el ejemplo del buscador de ficheros? Alli por ejemplo comentábamos su uso, que nos acercaba a uno de los patrones básicos de programación) . En este caso, C# introdujo la idea de esta construcción y Net Framework la ha promovido con la interfaz IEnumerator. Pero en nuestro caso, con Delphi 2007, la construcción se encuentra ya implementada en las estructuras básicas y puede ser usada en los caracteres de un string, en conjuntos, matrices y objetos que soporten GetEnumerator, que nos dara paso a que pueda ser usado en nuestra propias clases creadas.

En una próxima entrada hablaremos del operador Implicito y de algunos de los clásicos, esperando que no se me ocurra otra extravagancia como la aportada como ejemplo ;-) Lo importante al fin y al cabo es divertirse… :-)

Descargar el ejemplo: Aquí

OF TOPICCCCC :-)

¡Felicidades a la Selección Española de Futbol, la selección de mi país por el paso a las semifinales de la Eurocopa… ! ¡Increible! ¡Qué partidazo frente a Italia!

Plas!!! Plas!!! Plas!!!

Nos hemos quitado una espina que teníamos clavada desde hace un montonazo de años
Creo sinceramente que ha ganado el mejor.

Ya era hora que también nos sonriera la suerte!!!!!!!!!!!!!!
:-)

Posted by Posted by Administrador under Filed under Delphi, Código, Sintaxis, Entrada Diario, Artículos Comments No Comments »

Artículo Delphi Entrada Diario 

11th Jun 2008

Comentario intrascendente…

Siento la ausencia de estos días pero voy un poco sobrecargado de trabajo. :-( Y francamente, al llegar a casa, apenas me queda tiempo para escribir una sola linea. De hecho, tengo a medias la próxima entrada del Blog que continuaba profundizando en los cambios introducidos en Delphi 2007 y que no suelen ser demasiado conocidos.

El tema giraba sobre la sobrecarga de operadores, que ya es posible (y aquí viene la parte mas estrambótica) a nivel de la estructura de Registro. Se le pone a uno lo pelos como escarpias, cuando ve que es posible aplicar la sobrecarga en Delphi .Net a nivel de clases y que aquí nos hemos quedado como el tío faba (es una expresión de mi tierra) aplicando estas novedades a una estructura que en mi opinión tenía un menor peso especifico.

En fin… Desde Delphi 2 llevo oyendo a unos y a otros la importacia de las clases en la programación orientada a objetos, llenándose la boca de grandes discursos, para ver como ahora mismo, se le dota a la estructura de los registros, de unas funcionalidades que le acercan mas a las clases, sin que yo encuentre demasiado sentido a este giro… :-) Yo creo que hubiera sido mas oportuno haber dotado a una estructura como la clase de la sobrecarga de operadores pero posiblemente existan razones técnicas que queden mas allá de nuestro entendimiento para comprender el porque de una decisión como esta. Si hay alguien que lo entienda por favor que me lo explique.

Como dijo alguien en alguna ocasión, que cada mástil aguante su vela…

Posted by Posted by Administrador under Filed under Delphi, Entrada Diario, Artículos Comments No Comments »





  • free debugging software wordpress stats



    Nedstat Basic - Free web site statistics Libro de visitas