> On Sep 4, 2018, at 12:35 PM, Sven Barth via fpc-pascal > <fpc-pascal@lists.freepascal.org> wrote: > > I think you need to be clearer what you want to achieve in the end. The > default property as intended by Maciej has the idea that it hoists the > operators of the default property type to the record it is contained in.
Here’s my usage example which I encountered and got stuck with. The problem is I have a base class that has some commonly used functionality across many subclasses but at a later time I wanted to remove the fields from the class to save memory. Now I’m stuck with an OOP problem where I have tons of syntax like obj.RegisterMethod which are used in dozens of subclasses. The solutions currently are: 1) Put the two manager concepts into separate classes which can be subclassed. This may work in some instances but in others it breaks class hierarchies. If I want to include both I’m in trouble also because there’s no multiple inheritance in Pascal. 2) Put the two manager concepts into separate delegate classes which are included manually (delphi has the “implements” property but this doesn’t really do anything to help). This is more flexible but now I need to replace all calls as obj.methodManager.RegisterMethod which is 1) messy/long 2) introduces more names to remember and 3) will require lots of copy/paste. If I ever want to change it back I have hours of copy/pasting to do. type TBaseObject = class private methods: array of TMethod; objects: array of TObject; public { method manager } procedure RegisterMethod(name: string; proc: pointer); procedure InvokeMethod(name: string); { object manager } procedure ManageObject(obj: TObject); end; // if we need either of the 2 managers we need to inherit from TBaseObject // and take on the baggage. Typical OOP problems with deep class hierarchies. type TMyObject = class (TBaseObject) end; var obj: TMyObject; begin obj := TMyObject.Create; obj.RegisterMethod('foo', @method); obj.InvokeMethod('foo'); obj.ManageObject(otherObj); end. ======================================================================== Using what I’ll call the “alias property” for now (using “with” is not proper grammar Sven mentioned, and “default” implies just one, so...) we can pull out the two manager concepts into separate records and include them manually into any class we want. Thanks to having management operators now we can get automatic init/finalize to manage the lifecycle but I didn’t show that here. The alias property acts like the default property we’ve been discussing by calling into the fields namespace without the property name. This is the preferred solution for breaking up the class because once I add the manager record and the alias I don’t need to change any other code, everything works like before. What I propose is that the default property be allowed to support multiple default properties. The default property already basically does this so it’s just a matter of performing some searches before determining which property to use for the given call. If we made this safe it would be a good alternative to subclassing and allow for some really nice delegation patterns we can’t do in Pascal now. Clearly there are problems with name conflicts and precedence but surely they can be solved. There’s already a precedent of multiple interfaces in classes and redefining methods in subclasses so I don’t see why this can’t be made safe also. Please note the default property already introduces these problems so in my opinion it’s not that crazy to add more levels of search than just one. Here’s what the class looks like broken up into delegates and using aliases so they calling conventions don’t change from the original. type TMethodManager = record private methods: array of TMethod; public procedure RegisterMethod(name: string; proc: pointer); procedure InvokeMethod(name: string); end; type TObjectManager = record private objects: array of TObject; public procedure ManageObject(obj: TObject); end; type TMyObjectA = class private m_methodManager: TMethodManager; property methodManager: TMethodManager alias m_methodManager; end; type TMyObjectB = class private m_objectManager: TObjectManager; property objectManager: TObjectManager alias m_objectManager; end; var objA: TMyObjectA; objB: TMyObjectB; begin objA := TMyObjectA.Create; objA.RegisterMethod('foo', @method); objA.InvokeMethod('foo’); objB := TMyObjectB.Create; objB.ManageObject(otherObj); end. Regards, Ryan Joseph _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal