BotonMenu
BotonIndice

Visita : http://www.conoce3000.com
Paypal : https://www.paypal.me/conoce3000/1

PASCAL CON FREE PASCAL

PASCAL CON FREE PASCAL

PASCAL CON FREE PASCAL


10. INTRODUCCIÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS I.
10.3. CONSTRUCTORES Y DESTRUCTORES.
10. INTRODUCCIÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS I.
10.3. CONSTRUCTORES Y DESTRUCTORES.
10. INTRODUCCIÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS I.
10.3. CONSTRUCTORES Y DESTRUCTORES.

SIGUIENTE

SIGUIENTE

SIGUIENTE


‒ Constructores y destructores.

Los constructores son los métodos que se encargan de crear un objeto en el montículo, y los destructores son los métodos que se encargan de retirarlos del montículo. Al momento de crear un objeto de una determinada clase, para ejecutar el constructor correspondiente, se hace referencia con la clase y no con el objeto que se quiere crear. Esto debido a que el constructor es el encargado de crear el objeto en el montículo. Todas las clases tienen un constructor predefinido llamado Create, este como ya explique se encarga de crear el objeto en el montículo, pero también se encarga de inicializar todos los atributos automáticamente con ceros. De este modo si los atributos son números enteros o reales tendrán el valor 0, si son del tipo boolean tendrán el valor false, si es una cadena de caracteres tendrá una cadena de caracteres vacía, si es un carácter tendrá el carácter nulo, si es de tipo enumerado tendrá el valor inicial, siempre y cuando no se haya cambiado la enumeración de los tipos enumerados (es decir siempre deben comenzar en cero), y en el caso de los conjuntos tendrán un conjunto vació.

Cada vez que se crea un objeto, es preciso destruirlo. Si no se hace, la memoria utilizada en el montículo por el objeto no estará disponible para otro objeto, hasta que se finalice el programa.

Nuestras clases, pueden tener sus propios constructores, para ello se hace uso de la palabra reservada constructor. La declaración de un constructor se hace después de los atributos de una clase, en caso contrario el compilador generará un error de compilación. Un constructor también se puede utilizar para iniciar los atributos a un determinado valor, por ejemplo, a la clase TComplejos se le puede añadir un constructor para crear un número complejo con sus valores real e imaginario, sin usar los métodos PonReal y PonImag. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}

Unit Complejos02;
Interface

Type
  TComplejo = class
    ParteReal,ParteImag:double;
    Constructor Crear(r,i:double);
    Function ObtReal:double;
    Function ObtImag:double;
    Procedure PonReal(n:double);
    Procedure PonImag(n:double);
    Function ObtCad(dec:integer):string;
    Function PonCad(n:string):integer;
    Procedure Adicion(n:TComplejo);
    Procedure Multiplicacion(n:TComplejo);
  End;

Implementation

     Constructor TComplejo.Crear(r,i:double);
      Begin
        ParteReal:=r;
        ParteImag:=i;
      End;

    Function TComplejo.ObtReal:double;
      Begin
        ObtReal:=ParteReal
      End;

    Function TComplejo.ObtImag:double;
      Begin
        ObtImag:=ParteImag
      End;

    Procedure TComplejo.PonReal(n:double);
      Begin
        ParteReal:=n;
      End;

    Procedure TComplejo.PonImag(n:double);
      Begin
        ParteImag:=n
      End;

    Function TComplejo.ObtCad(dec:integer):string;
      var aux1,aux2,p:string;
      Begin
        p:='';
          Str(ParteReal:0:dec,aux1);
          Str(ParteImag:0:dec,aux2);
        if ParteImag>=0 then p:='+';
          ObtCad := aux1 + p +  aux2 + 'i';
      End;

      Function TComplejo.PonCad(n:string):integer;
      Var aux:string;
          p,i,error:integer;
          PR,PI:string;
          encontro:boolean;
      Begin
       aux:=n;
       ParteReal:=0;
       ParteImag:=0;
       error:=0;
       if (aux[length(aux)]='i') and (Not(aux[length(aux)-1]in['0'..'9']))
          then aux:=Copy(aux,1,length(aux)-1)+'1i';
       if aux[length(aux)]='i' then
         Begin
           delete(aux,length(aux),1);
           if aux[length(aux)] in ['0'..'9']
              then Begin
                     i:=length(aux);
                     encontro:=false;
                     p:=0;
                     while (not encontro) and (i>1) do
                      Begin
                       if (aux[i]='+') or (aux[i]='-')
                         then Begin
                               encontro:=true;
                               p:=i
                              end;
                       i:=i-1
                      End;
                     PR:=Copy(aux,1,p-1);
                     delete(aux,1,p-1);
                     PI:=aux;
                     Val(PR,ParteReal,error);
                     Val(PI,ParteImag,error);
                     if error<>0 then
                       Begin
                         ParteReal:=0;
                         ParteImag:=0
                       End
                   End;
         End
       else
        Begin
         Val(aux,ParteReal,error);
        End;
       PonCad:=error
      End;

    Procedure TComplejo.Adicion(n:TComplejo);
      Begin
        PonReal(ObtReal+n.ObtReal);
          PonImag(ObtImag+n.ObtImag)
      End;

    Procedure TComplejo.Multiplicacion(n:TComplejo);
      var PR,PI:double;
      Begin
       PR:=(ObtReal*n.ObtReal)-(ObtImag*n.ObtImag);
       PI:=(ObtReal*n.ObtImag)+(ObtImag*n.ObtReal);
       PonReal(PR);
         PonImag(PI)
      End;

End.
Código fuente 3: Unidad Complejos02 con el constructor Crear.
Descargar

Ahora el programa SumMul.pp, sólo usará los constructores para crear los números complejos. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses Complejos02;
Var Numero01,Numero02,Resultado:TComplejo;   
Begin
   Numero01:=TComplejo.Crear(3,5);
   Numero02:=TComplejo.Crear(5,2);
   Resultado:=TComplejo.Create;     
   
   Resultado.Crear(Numero01.ObtReal,Numero01.ObtImag);
   Resultado.Adicion(Numero02);   
   Writeln(Resultado.ObtCad(0));

   Resultado.Crear(Numero01.ObtReal,Numero01.ObtImag); 
   Resultado.Multiplicacion(Numero02);   
   Writeln(Resultado.ObtCad(0))
End.
Código fuente 4: Programa SumMul usando el constructor crear.
Descargar

Cómo se puede observar en el programa SumMul.pp, el objeto Resultado usa el constructor crear, para colocar la parte real e imaginaria del primer número complejo, antes de sumarlo o multiplicarlo. También se puede utilizar el constructor sobre un objeto ya creado; en ese caso no se crea un objeto en el montículo, pues ya existe, pero sin embrago se ejecutan las instrucciones del constructor. Es decir, si más adelante en el programa SumMul.pp, hacemos lo siguiente:

   Numero01:=TComplejo.Crear(3,5);
   ..
   ...
   Numero01.Crear(8,5)

Numero01, tendrá el número complejo 8+5i, y no con el que se ha creado 3+5i. Hay que tener cuidado con el uso de esta técnica, ya que si el objeto no ha sido creado, se produce un error en tiempo de ejecución. Es decir si no se hubiese creado el objeto Numero01, y se ejecutan las siguientes instrucciones:

   Numero01.Crear(8,5);
   Writeln(Numero01.ObtCad(0))

Se producirá un error en tiempo de ejecución, por el uso del método ObtCad, que hace referencia a un objeto que no se ha creado.

Todas las clases también tienen un destructor predefinido llamado Destroy. Para la implementación de un destructor propio para una clase, se procede de modo similar a la implementación de los constructores, excepto que la palabra reservada constructor se sustituye por la palabra reservada destructor, pero en una clase sólo debe haber un destructor y este no debe tener parámetros. Las instrucciones definidas en el destructor se ejecutan justo antes de liberar la memoria usada por el objeto.

El uso de los destructores dependerá de las circunstancias del programa, en el programa SumMul, en ningún momento se destruyen los objetos Numero01, Numero02 y resultado, ya que no es necesario, debido a la naturaleza del programa que es secuencial. Es decir todo objeto que se cree en un programa será destruido cuando el programa finalice.

Pero existen circunstancias en la que es necesario destruir el objeto, para que este no ocupe espacio de memoria en el montículo. A modo de ejemplo he creado el siguiente programa, en donde se hace uso de un procedimiento que permite intercambiar dos números complejos. El procedimiento usa un objeto aux, de la clase de TComplejo, que se crea dentro del procedimiento. La variable aux al ser un puntero, contiene una dirección de memoria al objeto que se crea en el montículo, cuando el procedimiento termina, la variable aux se borra de la pila, y si el objeto no es destruido entonces este existirá de manera inaccesible en el montículo, ocupando espacio que se puede aprovechar por otro objeto. Es en esta circunstancia cuando es necesario eliminar el objeto. A continuación el programa de ejemplo, este hace uso de la unidad Complejos.pp. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses Complejos02;
Var A,B:TComplejo;

Procedure Intercambio(A,B:TComplejo);
Var aux:TComplejo;
Begin
   aux:=TComplejo.crear(A.ObtReal,A.ObtImag);
   A.crear(B.ObtReal,B.ObtImag);
   B.crear(aux.ObtReal,aux.ObtImag);
   aux.destroy;
   aux:=nil;
End;

Begin
   A:=TComplejo.Crear(10,4);
   B:=TComplejo.Crear(0,1);
   Writeln('A=',A.ObtCad(0));
   Writeln('B=',B.ObtCad(0));
   Intercambio(A,B);
   Writeln('A=',A.ObtCad(0));
   Writeln('B=',B.ObtCad(0))
End.
Código fuente 5: Uso de destroy.
Descargar

Después de llamar al destructor se recomienda poner a nil la variable aux, para indicar que el objeto se ha eliminado. En este caso no es necesario pero es bueno mantener esta práctica.

Cuando un programa es demasiado complejo, suele suceder situaciones en la que no se puede saber anticipadamente si un objeto ha sido destruido en otra parte del código, con lo que puede suceder que se ejecute el método destroy por segunda vez ocasionando un error en tiempo de ejecución. Por lo que se recomienda en vez de usar el destructor destroy, usar el método free, que es un método, que por defecto lo tienen todas las clases en freepascal. Este método se encarga de verificar si realmente se elimino el objeto del montículo, comprobando si el objeto tiene el valor nil, en caso no se haya eliminado entonces este método ejecutará el destructor destroy, eliminando al objeto del montículo. Después de usar free, se debe colocar el objeto a nil, para indicar que este se ha eliminado y de ese modo cuando en otra parte del código se vuelve a usar otra vez el método free, este evitará usar el destructor del objeto que ya se ha destruido. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses Complejos02;
Var A,B:TComplejo;

Procedure Intercambio(A,B:TComplejo);
Var aux:TComplejo;
Begin
   aux:=TComplejo.crear(A.ObtReal,A.ObtImag);
   A.crear(B.ObtReal,B.ObtImag);
   B.crear(aux.ObtReal,aux.ObtImag);
   aux.free;
   aux:=nil;
End;

Begin
   A:=TComplejo.Crear(10,4);
   B:=TComplejo.Crear(0,1);
   Writeln('A=',A.ObtCad(0));
   Writeln('B=',B.ObtCad(0));
   Intercambio(A,B);
   Writeln('A=',A.ObtCad(0));
   Writeln('B=',B.ObtCad(0))
End.
Código fuente 6: Uso de free.
Descargar

Aunque se pueden crear destructores con un nombre propio o mejor dicho diferente a destroy, no es recomendable hacerlo si se usa el método free, ya que este ejecuta el destructor que tienen como nombre destroy y no ejecutará el definido por el usuario.


Última revisión: 16/06/2013.



SIGUIENTE
SIGUIENTE
SIGUIENTE


 
‒ Comentarios y sugerencias.

Agradezco de antemano, todo comentario, sugerencia, y donativo (a través de Paypal me), que ayude a mejorar los contenidos educativos de Conoce 3000. Además, cualquier pregunta o duda que tengas lo puedes hacer por este medio. Pero, todo contenido que pueda resultar ofensivo, malicioso, racista, sexista, discriminatorio, obsceno, vulgar será eliminado.








PORTADA |  INTERESANTE |  APUNTES |  LIBROS |  GALERIA


Creative Commons License


Todos los textos, imágenes y videos de Conoce3000 estan colocados bajo una licencia : Creative Commons Reconocimiento-NoComercial 3.0 Unported License.