[fpc-devel] Design ideas ... [[Re: Attn: Sven Can not use "specialize" to resolve forward declaration]]
Martin Frb
lazarus at mfriebe.de
Thu Dec 9 09:09:04 CET 2021
The below might read as if it belongs on the Lazarus list.
But this is not about Lazarus.
This is about a general design idea (pro and con), and the possibilities
the language provides.
The example(s) just happen to be from Lazarus.
On 09/12/2021 07:59, Sven Barth via fpc-devel wrote:
>
> For interfaces you can use IInterface/IUnknown though that will work
> only for COM interfaces. For raw interfaces there is no solution
> currently.
>
> In my opinion you should rethink your code structure however. I don't
> know right now what would be better, but as it is now it feels bad.
>
Well, ok, lets go fishing for ideas.
No rush, this is a loooong time think, no idea when I will really get to it.
Lazarus has a debugger frontend (currently more or less hardcode in the
IDE), and several backends (gdb/lldb/fpdebug/....)
The currently provided "interface" (for implementing a backend, that the
IDE can talk to) is just code taken from when we had only one backend.
However it is some elements, I like to keep. For different data elements
(stack,watches,locals) a Monitor/Supplier relation exists.
The backend is the supplier. The frontend the monitor. One think they
all have in common. They have a reference to each other.
For reasons outside this quest, the design should support multiple
Montiors, hence "Add/RemoveMonitor"
The WatchesSupplier takes one or more WatchesMonitor. The WatchesMonitor
has one WatcheSupplier.
On top of maintaining the relation, there will then be watches specific
methods.
So far so good.
https://gitlab.com/freepascal.org/fpc/source/-/issues/39459#note_758496897
represents this idea.
Using interfaces also seems a good idea. It does put the least
restrictions on both sides.
Especially each side can still choose it's own base classes.
-------
One more consideration. New methods could be added later. Then all
classes implementing the interface must implement them.
It would be nice, if a default could be automatically supplied.
(if/where such a default exists, e.g. CanFeature = false)
Actually that is possible too. generics
type TWatchesSupplierDef<_Base> = generic class(_Base, IWatchesSupplier)
... end; // having virtual methods for any method of the interface.
That still fulfils the initial requirements. Any implementer of the
interface can just mix it into their class structure
------
Now that still works. the problem starts when you want to split the
Inteface into a general base, and specifics for the watches/stack/locals.
At that point, the generic type restrictions no longer work.
Why splitting it? I could just repeat the 2 methods in the base?
Couldn't I?
But, maintaining the list of monitors could be completely implemented in
a generic (which later can be included in a monitor/supplier on a
optional base).
So, if I do not want to duplicate that code, then I need such a baseclass.
Currently that means giving up on some of the param-type-restrictions.
---------------------
Anyway that is the current background of what I am looking into.
> In my opinion you should rethink your code structure however. I don't
> know right now what would be better, but as it is now it feels bad.
Any better idea?
Btw, if that works, I have a feeling this could replace the LCL
interfaces run-time created classes. Afaik it fulfils all the
requirements that lead to the current situation.
- Being an interface
- having a default implementation
- allowing to mix default classes and specific classes into a new
inheritance structure.
More information about the fpc-devel
mailing list