Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-07

Property Tags

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Jorge Aldo G. de F. Junior

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.

Reply by email

Jorge Aldo G. de F. Junior
to leledumbo

and what about property tags and dynamic dispatch ?

this would solve a lot of problems of my project...

(i'm reading about multiple inheritance and looks like it creates more problems than it solves...)

on the other way looks like interfaces would make things more complex...

its there any technique to simulate multiple inheritance ? like those oop models people talk about (iterator, recall, command etc)

2010/8/2 leledumbo :

Show quoted text 15 lines
> 1 - How to simulate multiple inheritance ? Is there an alternative way > (Some other techniques, like interfaces etc) ? Err... we have interfaces since version 1.1. Check http://freepascal.org/docs-html/ref/refch7.html#x84-920007 this  out. -- View this message in context: http://old.nabble.com/Property-Tags-tp29315514p29324416.html Sent from the Free Pascal - General mailing list . _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Thierry Coq
to Jorge Aldo G. de F. Junior

Hello,

Jorge Aldo G. de F. Junior wrote 7 lines
and what about property tags and dynamic dispatch ? this would solve a lot of problems of my project... (i'm reading about multiple inheritance and looks like it creates more problems than it solves...)

...
Multiple implementation inheritance is quite a bad thing, it can render your code unreadable, and beyond that, plain wrong, with the error difficult to understand.
The answer in FPC are interfaces. In addition, to solve your particular problem, you might want to use generics (now possible in FPC) to limit the amount of similar code you write, and also use the responsibility and iterator patterns, but implementing them by using event properties (procedure of object properties), usually called
"OnSomethingDoSomething". This should decouple your code nicely.

I hope this helps.
Thierry

Reply by email

Jorge Aldo G. de F. Junior
to leledumbo

i already know about virtual metods,

by dynamic dispatch i mean to call a procedure by its name, at runtime, not at compile time...

i simply dont know how to do it (maybe object pascal doesnt support this ?)

2010/8/4 leledumbo :

Show quoted text 14 lines
> and what about property tags and dynamic dispatch ? AFAIR property tags aren't yet supported but dynamic dispatch is already supported with the virtual modifier. Check this out: http://www.freepascal.org/docs-html/ref/refsu25.html -- View this message in context: http://old.nabble.com/Property-Tags-tp29315514p29342617.html Sent from the Free Pascal - General mailing list . _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Marco van de Voort
to Jorge Aldo G. de F. Junior

In our previous episode, Jorge Aldo G. de F. Junior said:

Show quoted text 6 lines
i already know about virtual metods, by dynamic dispatch i mean to call a procedure by its name, at runtime, not at compile time... i simply dont know how to do it (maybe object pascal doesnt support this ?)

Two forms:

The first is only for published methods afaik, and that functionality is meant for framework internal use, so there is no short syntax.

(Lazarus uses this for its streamed messagehandlers, which are streamed as name)

The second is idispatch, the COM like way, which is used by interfaces to e.g. office applications and scripting languages.

Reply by email

Sven Barth
to Jorge Aldo G. de F. Junior: i already know about virtual metods, by dynamic dispatch i mean to call a procedure by…
Jorge Aldo G. de F. Junior wrote 7 lines
i already know about virtual metods, by dynamic dispatch i mean to call a procedure by its name, at runtime, not at compile time... i simply dont know how to do it (maybe object pascal doesnt support this ?)

You could try to use TObject.MethodAddress (
http://www.freepascal.org/docs-html/rtl/system/tobject.methodaddress.html ), but it might only work with published methods (I haven't tested it yet). Also you need to declare a method type to which the returned pointer can be cast to, so that you can call it like a "normal event handler".

Regards,
Sven

Reply by email