Introducción
El propósito de este artículo es explicar cómo usar objetos para sustituir a los viejos archivos de inicio (y otras técnicas similares) para guardar parámetros de configuración de una aplicación. El uso de objetos nos permitirá ahorrar tiempo de codificación, reducir la posibilidad de errores, encapsular los parámetros de configuración, usar archivos o el registro de windows sin inconvenientes, etc, etc.
Problemas al usar archivos de inicio
Algunas de las desventajas asociadas al uso de archivos .ini:
IniFile.WriteString( 'Main','LastUser', UserName); //« LastUser
y leemos usando esta instrucción
UserName := IniFile.ReadString('Main', 'LatsUser', ''); //LatsUser
Nunca podremos recuperar la información almacenada. (Puede solucionarse usando constantes, pero implica más declaraciones y asignaciones.)
La gran solución : OBJETOS
(NOTA: El código del demo adjunto contiene más detalles y comentarios, que han sido omitidos en el texto de este artículo.)
Observemos esta declaración
TOpciones = class(TComponent)
//....
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
procedure ReadConfig;
procedure SaveConfig;
property ScrennRes: TPoint read GetScrennRes;
published
property NoSplash : Boolean read fNoSpl write fNoSpl;
property UserName : string read FUserName write SetUserName;
property Lines : TStrings read fLin write fLin;
property Font : TFont read FFont write SetFont;
property LastUse : TDateTime read fLastUse write flastUse;
{....más propiedades....}
end;
La idea principal es crear una clase (que herede de TComponent), definir un par de propiedades, escribir un par de procedimientos y listo.
¿Cuánto vivirá nuestro objeto? Para aplicaciones medianas y chichas sólo hace falta un objeto de configuración y puede ser necesario que exista desde que se crea la aplicación. Para asegurarnos de que el objeto estará siempre disponible escribimos final de la unit (antes del end.)
initialization
Opciones := TOpciones.Create(nil);
Opciones.ReadConfig;
finalization
Opciones.Free;
//Este es el end. de la unit
end.
Esto nos permitirá utilizar el objeto desde cualquier parte de nuestra aplicación (incluso desde el archivo .DPR ! -Ver demo adjunto- )
Propiedades
A continuación veremos algunas alternativas para declarar las propiedades, utilizaremos una u otra dependiendo de las restricciones que tengamos.
Las propiedades pueden declararse en la sección protected, public y published, sólo las declaradas dentro de published serán almacenadas con el objeto.
Declaración Básica: En esta declaración la parte de lectura (read) y la de escritura (write) hacen referencia a una misma variable interna. Luego de escribir la instrucción
property NoSplash: Boolean read fNoSplash write fNoSplash;
presionamos Ctrl + Shift + C y Delphi crea una variable privada FNoSplash del tipo boolean. De esta manera no podemos restringir los valores que se asignan a la variable ni controlar el formato con que se muestra.
¿Cómo funciona? Cuando escribimos… el compilador lo traduce en …
Opciones.NoSplash := False; Opciones.FNoSplash := False;
Ch.checked := Opciones.NoSplash ch.checked := Opciones.FNoSplash;
Declaración con Restricciones: En esta declaración la parte de escritura se cambia la variable por un procedimiento. (El nombre del procedimiento puede ser cualquiera, por convención es SET + nombre de la propiedad). Luego de escribir
property Lines: TStrings read fLines write SetLines;
presionamos Ctrl + Shift + C y Delphi crea una variable privada fLines del tipo TStrings y un procedimiento privado SetLines más el cuerpo del mismo.
procedure TOpciones.SetLines(const Value: TStrings);
begin
fLines.Assign(Value); //Nunca hacer fLines := Value;
end;
NOTA: Dentro del procedimiento se debe usar la variable interna FLines y NO hacer referencia a Lines. Si dentro de el procedimiento SetLines cambiamos FLines por Lines se producirá una llamada recursiva al procedimiento terminando en un horrible desbordamiento de pila.
NOTA: Si la propiedad es un objeto (TFont, TStrings o cualquier otro heredero de TObject) SIEMPRE se debe utilizar este tipo de declaraciones de propiedades para hacer una copia local (usando assign u otro método), sino la asignación se convierte en una asignación de punteros.
En el cuerpo del procedimiento podemos realizar validaciones para determinar si asignamos o no el valor a la propiedad interna, mostrar mensajes o errores, llamar a otros procedimientos/funciones, modificar otras propiedades, etc (ve en el código del demo adjunto la propiedad UserName)
¿Cómo funciona?
Cuando escribimos… el compilador lo traduce en …
Opciones.Lines := Memo1.Lines; Opciones.SetLines(Memo1.Lines);
cbx.Lines := Opciones.Lines; cbx.Lines := Opciones.FLines;
Ważne artykuły