PDA

Ver la Versión Completa : Cuando y por que usar property


David
30-10-2006, 21:09:06
Hola

Estoy leyendo en la cara oculta de delphi 4 , el uso de propiedades (property) y la verdad este tio que escribe el libro se enrolla y se va del tema y al final no me he enterado la utilidad de esto .

Alguien me puede decir algunos ejemplos en los que es conveniente utilizar estas propiedades .

De lo que me he enterado es de como se forma :

Property NombrePropieda : Tipo read FNombrePropiedad write SetNombrePropiedad;

Y que puede ser read and write o sólo read , y write sólo casi nunca .

Pero no sé exactamente , cuando usarlas y por qué .

Saludos

donki
30-10-2006, 22:55:02
Miraré de explicartelo:

La propiedades son como variables que otras classes pueden ver.

Las propiedades se guardan internamente dentro de la classe por unas variables assignadas en la declaración de la propiedad:

En tu ejemplo FNombrePropiedad es una variable privada (por convenio) de la classe. Tambien en tu ejemplo hay el procedure SetNombrePropiedad. Este procedure asignará el valor a la propiedad y te permitirá hacer más cosas en ese momento. Podrias tener una función GetNombrePropiedad. Esta función te permitiria obtener el valor de la propiedad( por ejemplo si fuera calculada)

Sobre lo del read y el write es bastante trivial, simplemente indicas que se lee (read) con la función o con la variable y se escribe (write) con el procedure o la variable

Espero que te ayude

hector.roma
31-10-2006, 00:58:33
A que me refiero con esto... imagínate que tienes dos clases:
TVariable=class
public
miVariable : string;
end;

TPropiedad=class
private
FmiVariable : string
published
property miVariable : string read FmiVariable write FmiVariable;
end;


Como puedes ver las dos clases hacen lo mismo:
var
Variable : TVariable;
Propiedad : TPropiedad;
...
begin
Variable.miVariable := 'Hola variable';
Propiedad.miVariable := 'Hola propiedad';
end;


y podría parecer que es más cómodo al principio usar la clase TVariable en vez de de la clase TPropiedad pues "hay que escribir menos".

Sin embargo dejamos de lado el presente y avanzamos al futuro... ahora nos damos cuenta que queremos mostrar un mensaje de error si el valor del campo miVariable es una cadena vacía.

Desde la primera aproximación tenemos dos formas, bien verificamos fuera de la clase el valor introducido o bien añadimos un método que valide el texto introducido y en ambos casos recorremos nuestro código en busca de todas las veces que modificamos el valor de miVariable para añadir los cambios.
Sin embargo, si hemos usado propiedades el resultado podría quedar algo así:
TPropiedad=class
private
FmiVariable : string
published
property miVariable : string read FmiVariable write setTexto;
end;


donde setTexto sería la función que nos valida el texto introducido.

Espero que este ejemplo te ayude a explorar más detenidamente el tema de las propiedades.

jachguate
31-10-2006, 01:49:24
sigo con la idea de Hector.

Las propiedades son útiles también para introducir "efectos secundarios".

Supongamos que estas programando una clase:


TEtiquetaV = class(TObject)
public
Mensaje : string;
end;

TEtiquetaP = class(TObject)
FMensaje: string;
public
property Mensaje: string read FMensaje write FMensaje;


Mas adelante... mientras vas programando el sistema, te das cuenta que queres que el mensaje de la etiqueta se actualice automáticamente en la pantalla cuando el programador lo asigne, de manera que el usuario tenga un retorno de información adecuado.

Entonces, en lugar de escribir el valor de la propiedad directamente en FMensaje, creas un método SetMensaje (o cualquier otro nombre, aunque esta es la convención) y lo implementas algo como:


TEtiquetaP = class(TObject)
FMensaje: string;
procedure SetMensaje(const Value: string);
public
property Mensaje: string read FMensaje write SetMensaje;
end;

....

procedure TEtiquetaP.SetMensaje(const Value: string);
begin
FMensaje := Value;
Repintar();
end;


Luego, te das cuenta que sería de utilidad al programador poder actuar cuando hay un cambio en el valor de la propiedad mensaje de la etiqueta.

Entonces añadis un evento a la clase y lo lanzas cuando cambia el valor:


procedure TEtiquetaP.SetMensaje(const Value: string);
begin
FMensaje := Value;
Repintar();
DoOnChange;
end;


En fin... usar propiedades te ayuda a mantener una interfaz consistente al programador a medida que tus clases evolucionan, validar automáticamente los valores que la clase acepta en las propiedades (por ejemplo, solo números pares o impares, etc), introducir efectos secundarios "controlados", lanzar eventos.

Hasta luego.

;)

David
31-10-2006, 15:20:42
En el ejemplo de Jachguate no llego a comprender , que tiene que ver la clase TEtiquetaV

Por otro lado , según me dijeron tenia que programar una propiedad en mi programa y lo he hecho de esta manera y me funciona , aunque no sé si es la forma más correcta .

Tengo un Datamodule y un FrmReformas .

En el Datamodule ,tengo la tabla de reformas , TReformas con su datasource , y en el formulario tengo una tabla de componentes que corresponde a cada reforma . De tal manera que si en el formulario de Reformas , vas recorriendo la tabla de Reformas , tienen que ir apareciendo los componentes de dicha reforma .

Para ello , la tabla TComponentes , hago un filter para igualar el campo de reforma con el código de la tabla reforma .

Asi en el Datamodule tengo esto :


private
{ Private declarations }
FNotifyToTFReformas:TDataChangeEvent;

public
{ Public declarations }
property NotifyToTFReformas:TDataChangeEvent read FNotifyToTFReformas
write FNotifyToTFReformas;

// Después en el datasource de la tabla Reformas (esta en el DM)

implementation
procedure TDM.dsReformasDataChange(Sender: TObject; Field: TField);
begin
If Assigned(FNotifyToTFReformas) Then
Begin
FNotifyToTFReformas(Sender, Field);
// luego pongo más código .... (no tiene que ver con el caso)

end;


Bien esto es lo que he puesto en el DataModule , ahora en el formulario FReformas , donde esta la tabla componentes , he puesto lo siguiente


public
// Declaro un procedure
procedure ReformaDataChange(Sender: TObject; Field: TField);

implementation
procedure TFReformaDataChange(Sender: TObject; Field: TField);
begin
Caption := ' Reforma : ' + DM.TReformas.FieldByName('titulo').AsString + ' ';
TComponentes.Filter:='icodReforma = '''+DM.TReformas.FieldByName('Codigo').AsInteger+'''';
// Aquí aprovecho para cambiar otro Query de Componentes
end;

// después en el evento Oncreate , hago esto

procedure TFReformas.FormCreate(Sender: TObject);
begin
DM.NotifyToTFReformas:=ReformaDataChange;
end;

// y en el evento Onclose , donde el formulario se destruye , aprovecho para
//decir que el formulario es fsMDIChild y se crea y se destruye al entrar y
//salir -> Action := caFree.

procedure TFReformas.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DM.NotifyToTFReformas:= nil;
end;

jachguate
31-10-2006, 20:02:27
Está bien como práctica de clase, aunque no le hallo sentido a lanzar un evento de esta manera, pues bastaría poner un DataSource asociado al dataset en el módulo de datos en el formulario y atender el evento OnDataChange de este.

Hasta luego.

;)

donki
01-11-2006, 12:07:57
Hola,

Hay que aclarar una cosa, las clases, objetos, interficie, no se utilizan por que si. Nadie se pondrá a hacer una clase para guardar un solo valor.

Tened en cuenta que las clases nacen de modelar los objetos de un problema y tienen su semantica dentro del problema que quieres resolver.

Resumiendo, la teoria de programación orientada a objetos tiene unas especificaciones que a priori no sirven para nada, pero que en diseños complejos pueden salvarte de tener que hacer miles de "xapuzas" para ajustarte al diseño.

No es que sea un purista de las OOP, pero va muy bien conocer todas estas opciones.