[fpc-pascal] Property Tags
Jorge Aldo G. de F. Junior
jagfj80 at gmail.com
Sun Aug 1 00:52:56 CEST 2010
Hello !
I'm writing a ActiveRecord system for Freepascal (Something similar to
what RubyOnRails do), and i am having some problems (I'm not following
MVC logic, more of a Exposed Object Logic) :
1 - How to simulate multiple inheritance ? Is there an alternative way
(Some other techniques, like interfaces etc) ?
I have, for exemple, in the visual components the following :
TVisualComponent wich can be hidden or shown (Property Visible)
and another component called TCollapsibleComponent wich can have its
childs shown (while keeping itself visible) or hidden.
So, sometimes i want another component to descend from
TVisualComponent, sometimes i want a component to descend from
TCollapsibleComponent, while sometimes i want it to descend from
both...
I solved this by making TCollpasibleComponent descent from
TVisualComponent, but... this is quite hackish, as if i want the
descendent to not allow visibility toggles i have to override the
method wich makes it visible or not and replace it with a dummy method
wich does nothing :
TVisibleComponent = Class(something)
Public
Procedure DoVisible; Virtual;
Procedure DoInvisible; Virtual;
End
TCollapsibleComponent = Class(TVisibleComponent)
Public
Procedure DoCollapse; Virtual;
Procedure DoUncollapse; Virtual;
End;
TSomeComponentWichShouldOnlyBeCollapsible = Class(TCollapsibleComponent)
Public
Procedure DoInvisible; Override; // <- dummy method wich dont call
inherited so as to deny invisibility
End;
In this case the problem is easily solved, but there are other parts
of the class tree of my project that makes this a headache (i have to
make properties dissappear from published section etc, write dummy
methods etc).
There are any plas to add mixins to freepascal ?
2 - Published properties tagging :
Some time ago i saw some discussion about adding property tags to
freepascal. This is a GREAT idea !
In the model i am using, the published properties of an object can go
to various places :
They can be edited in runtime by their name (something like
myobject.properties[<nameofpublished>] := 'something')
They can be stored in a database,
They can be shown in the screen,
They can represent a many to one relationship between object collecions, etc.
So, currently i have to use some hacks to keep track of wich
properties do what :
Like this
Type
TMyObject = Class(TExposedProperties) // this object can end up in the
screen template,, edited back thru a CGI Post, in a database or in
streamed to a session file
Private
fEditable: TArrayOfString; // Holds wich property can be edited by CGI
fStreamable : TArrayOfString; // holds wich property goes to/from
the session data stream
fPersist : TArrayOfString; // holds wich property goes to/from the database
fTemplate : TArrayOfString; // holds wich property goes to the template system
Published
Property SomeProp : Integer Read Getter Write Setter;
End;
TMyObjectChild = Class(TMyObject)
Constructor Create...
AddEditable('someprop');
AddStreamable('someprop');
AddPersist('someprop');
AddTemplate('someprop'); For each property...
And this is not much maintanable...
What i propose :
a kind of visibility overloading.
the objectpascal syntax for class is like this (not exactly) :
Type
<classname> = Class(<ancestor>)
[ <visibility> ]
<classfield> [ ; <classfield> [...] ]
End;
i propose :
Type
<classname> = Class(<ancestor>)
Tag <visibilitytag> [ Write fVisibilityWriter ] ;
Published
[ <tag> ] Property <nameeetc>;
end;
Example :
Type
MyClass = Class(TObject)
Private
fPrivatefield : Integer;
Procedure NewStreamableProperty(Const aPropname : String;
aPropkind : TRTTIInfo);
Tag Streamable Write NewStreamableProperty;
Published
Streamable Property PrivateField Read fPrivateField Write fPrivateField;
End;
The property is internally tagged with "streamable" for later use and
after the object is constructed (with RTTI Info) the writer (if
defined), NewStreamableProperty, is called with Property PrivateField
as parameters (his name and TRTTInfo), so as to allow the programmer
to store this information for his own use (this allows derived classes
to simply tag its properties and allow the root class to manage this).
The writer is just a way to tell wich method to call to inform that
the property is tagged, but is optional, the real tagging should be
interntal to TObject to allow the following :
If PrivateField Is Streamable Then // <- overload "is" to allow
comparing properties to tags...
Tags should be like sets :
Type
Myclass = Class(TObject)
Private
fField : Integer;
Tag Streamable;
Tag Storable;
Tag Visible;
Tag Editable;
Published
Streamable Storable Visible Editable Property Field: Integer Read
fField Write fField;
End;
Well, this is just a proposal, any other form of property Tagging
would help me. the experience tells me that this is usefull. The only
other way around without property tagging is using some RTTI Hacks :
Type
TEditableInteger = Integer;
TStreamableInteger = Integer;
TEditableStreamableInteger = Integer;
And looking the RTTI for the property type name (THIS SUUUUUX A LOT,
imagine the ammount of combination types needed...)
3 - Better rtti :
Sometimes i need to invoke methods by name, and sincerely i never
discovered the correct way to do this with RTTI...
I am currently using a hack based on DispatchStr, and this works quite
well, apart from the hackish way to return results (i can pass a Array
of Const as parameters, but its not easy to return data back...)...
if you could add something similar to DispatchStr with the ability to
return variants, this would be ok to me...
Type
TObjectMessage = Record
MessageString : String[255];
MessageParameters : Array Of Variant; // <- original was a pointer
End;
MyObject = Class(TObject)
Function SomeMethod(Var Message : TObjectMessage): Variant; Message
'onsomething';
End;
then use :
Data := MyObject.DispatchStr('onsomething', [ 'parameter1', parameter2 ]);
would be ok and solve most of my problems...
Well, i i know you program for free and you are not at my disposal
etc. But i am trying to share some experience here from what i
discovered while trying to develop this activerecords thing...
thank you in advance,
J. Aldo.
More information about the fpc-pascal
mailing list