Solución al Koan #1
CUANDO UNO SON DOS Y DOS SON UNO
En este caso, la solución es muy sencilla: hay que darse cuenta de que Memo.Font
(y también FontDialog1.Font) no es una variable de clase, sino una propiedad de tipo clase ... y que las propiedades, aunque intentan engañarnos haciéndose pasar por variables, realmente no lo son. La propiedad Font se implementa generalmente del siguiente modo:
type
TLoQueSea = class(TOtraCosa)
// ...
private
FFont: TFont;
procedure SetFont(Value: TFont);
published
property Font: TFont read FFont write SetFont;
end;
La implementación del método de escritura SetFont es la siguiente:
procedure TLoQueSea.SetFont(Value: TFont);
begin
FFont.Assign(Value);
end;
El método Assign es introducido por la clase TPersistent (ancestro de TComponent) y debe ser redefinido por aquellas clases que deseen implementar la asignación de objetos "propiedad por propiedad". En la jerga informática, a este tipo de asignación se le llama asignación por valor, en contraste con la asignación por referencia, que es la implementada por el operador de asignación de Delphi para las variables de tipo clase.
De modo que en el primer ejemplo realmente estabamos asignando el puntero del objeto original a la variable F, precisamente por tratarse de una variable. En el segundo ejemplo, la asignación se realizaba a una propiedad de tipo Font, y Delphi implementa las asignaciones a este tipo de propiedades como asignaciones por valor.
¿Hasta que punto podemos fiarnos de que Delphi implemente para todas sus propiedades de tipo clase asignaciones por valor? Se trata de una recomendación metodológica, que Delphi (hasta donde sé) cumple escrupulosamente. Cuando usted implemente una propiedad de tipo clase debe tener cuidado y ajustarse a este comportamiento. Por ejemplo, es fácil perder de vista el hecho de que la variable interna FFont debe ser construida a la vez que la clase que la contiene (y destruida en Destroy):
constructor TLoQueSea.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFont := TFont.Create;
// ...
end;
También es muy fácil olvidar el requisito de que la clase para la cual se define la propiedad debe contar con una implementación correcta del método Assign.
|