'

‒ Atributos, propiedades, métodos de clase y métodos estáticos.

Al definir un atributo de una clase, lo que se hace es indicar que ese atributo se debe crear para cada objeto o instancia que se cree de la clase. Es decir cada objeto o instancia tiene su propia representación independiente del atributo. Pero sin embargo es muy útil tener un atributo compartido por todos los objetos de la clase, a esos atributos se les conoce como atributos de clase, un atributo de clase se relaciona con la clase, pero no con los objetos o instancias.

Para definir atributos de clase se debe colocar antes las palabras reservadas class y var, para luego colocar los atributos, el bloque de atributos de clase se debe finalizar con la palabra reservada var. Ver ejemplo:

TAvion=class
  class var
  aviones:integer; //atributos o variables de clase
  colorado:integer;
  var
  constructor create;
  Procedure Despegar;virtual;abstract;
End;

Para acceder a un atributo de clase, sólo es necesario usar la clase, no obstante un objeto o instancia, también se puede usar para acceder al atributo de clase. Esto nos dice que el atributo de clase se puede usar sin haberse creado el objeto.

Los métodos de clase al igual que los atributos de clase, son métodos que se relacionan con las clases y no con los objetos o instancias, esto también nos permite tener un método compartido que funcionará igual en todas las instancias que se creen, pero dentro de los métodos de clase sólo se pueden acceder a atributos de clase,

Al igual que los atributos el método de clase se puede usar sin haberse creado el objeto. Un ejemplo de un método de clase es el método ClassType que se explicó en el capitulo anterior. Para declarar un método de clase en free pascal, sólo hay que añadir la palabra clave class delante del método.

Type   TClaseA = class
  class procedure Escribe;

Los métodos de clase también pueden ser virtuales, por lo que se pueden sobre-escribir y usar para crear polimorfismo. Los métodos de clase se pueden ejecutar usando una clase como así también usando un objeto.

Var A:TClaseA
Begin
.
..
TClaseA.Escribe;
A.Escribe; //El objeto A debe ser creado con anterioridad

El parámetro oculto self de un método de clase, es una referencia a la clase de donde el método de clase es ejecutado, Si él método de clase es ejecutado con la clase TClaseA, entonces self es la clase TClaseA, y si este es ejecutado con un Objeto entonces self tendrá una referencia de la clase del objeto. Sin embargo, dentro de un método de clase no se puede usar self para acceder a los atributos, propiedades y métodos normales, pero si se puede usar para ejecutar constructores y otros métodos de clase, atributos de clase y propiedades de clase.

Las propiedades de clase son similares a las propiedades normales, pero sólo trabajan con atributos de clase y métodos de clase estáticos. Los métodos de clase que hemos visto no se pueden usar con las propiedades de clase, para ello es necesario convertir un método de clase a un método estático colocando al final del método de clase la palabra reservada static, con eso convertimos al método de clase en un método estático, cuando un método de clase se hace estático este ya no se puede usar como métodos virtuales, es decir ya no se puede hacer polimorfismo. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils;
Type
     
     TClassAvion=Class of TAvion;
     TAvion=class
       class var
         FAviones:integer; //atributos o variables de clase
       var
         Nombre:string;
       constructor create;
       class function ObtAviones:integer; static;   
       class property aviones:integer read ObtAviones;

       Procedure Despegar;virtual;abstract;

     End;
 
     TAvComercial=class(TAvion)
       Procedure Despegar;override;
     End;

     TAvGuerra=class(TAvComercial)
      Procedure Despegar;override;
     End;

     TEscenario=Class
         Ref:TClassAvion;
         A:array of TAvion;
         Procedure GenerarAvionesAzar;
     End;

     Constructor TAvion.create;
      Begin
        inherited create;
        Faviones +=1
      End;

     class function TAvion.ObtAviones:integer;
      Begin
       ObtAviones:=FAviones
      End;

     Procedure TAvComercial.Despegar;
      Begin
        Writeln('Despegando Avion Comercial '+Nombre);
      End;
     Procedure TAvGuerra.Despegar;
      Begin
        Writeln('Despegando Avion de Guerra '+Nombre);
      End;

     Procedure TEscenario.GenerarAvionesAzar;
      Var i,j,c:integer; 
      Begin
       randomize;
       c:=random(100);
       setlength(A,c);
       for i:=1 to c-1 do
        Begin
         j:=random(150);
         if (j mod 2) = 0 then ref:=TAvComercial
                          else ref:=TAvGuerra;
         A[i]:=ref.create;
         A[i].Nombre:=IntToStr(i);
         A[i].despegar;
        End;
       Writeln(TAvion.aviones,' aviones creados');
     End;

Var Escenario:TEscenario;
Begin
  Escenario:=TEscenario.create;
  Escenario.GenerarAvionesAzar  
End.
Código fuente 21: Ejemplo del uso de un atributo de clase como un contador de objetos.
Descargar

Tal como se puede observar en el ejemplo el uso de atributos de clase, métodos de clase y propiedades de clase es el de definir contadores como el atributo aviones, que se comparte con todos los objetos creados, ya que como se menciono anteriormente, cada vez que se crea un avión en memoria, no se separa un espacio de memoria para el atributo aviones por cada avión que se crea, ya que este existe en la propia clase TAvion. Si el atributo aviones, no hubiese sido un atributo de clase entonces cada vez que se crea un avión, el atributo aviones de cada instancia sólo tendría el valor de 1.

Los atributos de clase también se pueden usar como variables de control de un bucle For, siempre y cuando sean del tipo entero, enumerado o carácter, esto es debido a que un atributo de clase se comporta como una variable global, y como ya se conoce de lo explicado en capítulos anteriores, un bucle For, admite el uso de variables globales como variables de control. A continuación un ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}

Type TCualquierClase=class
      class var
        j:integer; //variable de control
      var
      Procedure Prueba;
     End;

     Procedure TCualquierClase.Prueba;
      Begin
        for j:=1 to 10 do Writeln(j);
      End;

Var MiClase:TCualquierClase;
Begin
 MiClase:=TCualquierClase.Create;
 MiClase.Prueba
End.
Código fuente 22: Ejemplo del uso de un atributo de clase como un contador de objetos.
Descargar

Como se puede ver en este ejemplo el atributo de clase con identificador j, se puede usar como una variable de control del bucle For. No obstante al ser un atributo de clase, se debe tener presente que este atributo es compartido por todas las instancias de la clase.


Última revisión: 26/02/2014.