Discussion:
Different "default" value for a property in derivedclass
Jether (yahoo)
2013-04-06 17:19:38 UTC
Permalink
This doesn't make any sense to me, TB is descendent of TA, TB should never
affect the behavior of it's ancestror TA.

Jether Fernandes Reis
-----Mensagem Original-----
De: "Bart" <***@gmail.com>
Para: "Lazarus mailing list" <***@lists.lazarus.freepascal.org>
Enviada em: sábado, 6 de abril de 2013 11:52
Assunto: Re: [Lazarus] Different "default" value for a property in
derivedclass
TB = class(TA)
....
property foo default stB;
end;
Yes, that did it.
I tried something like that, but didn't get the syntax right.
Thanks a lot.
Bart
--
_______________________________________________
Lazarus mailing list
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
--
Michael Van Canneyt
2013-04-06 14:21:14 UTC
Permalink
Hi,
Consider this.
type
TSomeType = (stA, stB, stC);
{ TA }
TA = class
private
FFoo: TSomeType;
public
constructor Create; virtual;
published
property Foo: TSomeType read FFoo write FFoo default stA;
end;
{ TB }
TB = class(TA)
public
constructor Create; override;
end;
implementation
{ TB }
constructor TB.Create;
begin
inherited Create;
Foo := stB;
end;
{ TA }
constructor TA.Create;
begin
FFoo := stA;
end;
Now imagine that you drop an instance ot TB on a form.
In OI you set Foo to stA.
You build and run, and to your surprise Foo is stB.
You think for a while and realize what happened: since property TA.Foo
is declared with "default stA", this means that if you set Foo in OI
to stA it is not streamed to the LFM.
So far, so good.
Now the question: is there any other way to fix this besides removing
the "default stA' from the declaration of the TA.Foo property?
(Assuming that it is necessary for TB to set Foo to stB by default).
Just change the default:

TB = class(TA)
public
constructor Create; override;
published
property foo default stB;
end;

Michael.

--
Bart
2013-04-06 14:52:47 UTC
Permalink
TB = class(TA)
....
property foo default stB;
end;
Yes, that did it.
I tried something like that, but didn't get the syntax right.

Thanks a lot.

Bart

--
Hans-Peter Diettrich
2013-04-06 19:23:08 UTC
Permalink
Post by Jether (yahoo)
This doesn't make any sense to me, TB is descendent of TA, TB should
never affect the behavior of it's ancestror TA.
Properties are evaluated at compile time. When an object reference is
known to be of type TB, the compiler uses the getter/setter methods of TB.

Nonetheless I don't understand what initialized properties in
non-component classes are good for, together with the observed behaviour
of default values. Can somebody point me to the according documentation?

DoDi


--
Sven Barth
2013-04-06 22:03:36 UTC
Permalink
Post by Hans-Peter Diettrich
Nonetheless I don't understand what initialized properties in
non-component classes are good for, together with the observed behaviour
of default values. Can somebody point me to the according documentation?
Streaming is introduced with TPersistent (or to be more precise: with
any class declared when $M+ is set), so one can use this for streaming
ones own classes or to build a different GUI toolkit (e.g. in theory
Graeme could use the streaming for fpGUI as well).

Regards,
Sven

--
Graeme Geldenhuys
2013-04-07 00:17:19 UTC
Permalink
Hi Hans-Peter,
Post by Sven Barth
ones own classes or to build a different GUI toolkit (e.g. in theory
Graeme could use the streaming for fpGUI as well).
I consciously decided not to use streaming in fpGUI (but in theory I
could have, yes). I do use RTTI in the fpGUI Forms Designer though, to
reduce the amount of Object Pascal code the form designer generates. eg:
For RTTI to work, properties must be Published. I then check those
properties, and see if they are equal to their default values, in which
case I don't generate Object Pascal code.


Regards,
- Graeme -
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/


--
Michael Van Canneyt
2013-04-06 22:18:18 UTC
Permalink
Post by Jether (yahoo)
This doesn't make any sense to me, TB is descendent of TA, TB should never
affect the behavior of it's ancestror TA.
Properties are evaluated at compile time. When an object reference is known
to be of type TB, the compiler uses the getter/setter methods of TB.
Nonetheless I don't understand what initialized properties in non-component
classes are good for, together with the observed behaviour of default
values. Can somebody point me to the according documentation?
Default values are simply stored in RTTI.
RTTI is generated for all TPersistence descendents such as TStrings or TCollectionItem.
(or as Sven pointed out, any descendent of a class compiled in {$M+})

They have no other purpose than inform a streaming implementation what the
default value is expected to be after the constructor was called.

There is no guarantee from the compiler that this will actually be the case.
It depends on the constructor of the class.

This can be used to:

* omit values when streaming the component. This is what is currently done.

* One could imagine an implementation in a class that retrieves all default values and
initializes them "automatically". However, this can have side-effects if there is a
property setter, so it is not implemented in TComponent.

All this is documented in the language reference manual:

http://www.freepascal.org/docs-html/ref/refsu37.html

Michael.

--
Graeme Geldenhuys
2013-04-07 00:13:06 UTC
Permalink
Post by Jether (yahoo)
This doesn't make any sense to me, TB is descendent of TA, TB should never
affect the behavior of it's ancestror TA.
TB doesn't affect the behaviour of TA. TB extends or descends from TA,
altering its own behaviour. That is the purpose of descendants - add or
change functionality. Because TB changed the default value in the
constructor, it should also notify the RTTI system about that change,
hence the redeclared property with a new 'default stB' text.



Regards,
- Graeme -
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/


--
Loading...