[Gambas-user] How to use a virtual class in gambas
brian at westwoodsvcs.com
Mon Jan 27 19:01:17 CET 2020
Thank you so much for your very clear description!
I begin to see how this is done.
I am grateful that you have taken the time to be so detailed!
Thanks again Tobi!
----- Original Message -----
From: "Tobias Boege" <taboege at gmail.com>
To: "Gambas mailing list" <user at lists.gambas-basic.org>
Sent: Saturday, January 25, 2020 3:56:26 AM
Subject: Re: [Gambas-user] How to use a virtual class in gambas
On Fri, 24 Jan 2020, Brian G wrote:
> Thanks for your reply Christof and no I did not know about our search engine!
> Ok After reading from the thread, and searching for other Ref. I see in my understanding that
> unless I am writing C++ there is in fact no real virtual class[interface] to underlying classes/Object.
> I looked into the ARRAY class and see that the .Array.Bounds class is used a
> GB_PROPERTY_SELF for that object .
> I am trying to create a class which inherits array cant seem to get the bounds working...
> Am I missing something.. or is there actually a way to use virtual gambas classes.
> Maybe I don't understand how to link the virtual object to the underlying real object. and return
> it from a call to a read property.
It works like this in native components: using the interpreter API you can
implement classes accessible to Gambas programs in C or C++. You just have
to give the interpreter a certain binary blob describing the class interface,
what names methods and properties have, which arguments they receive,
which types they return, and then you say how much storage the object takes.
When the Gambas program uses properties and methods, the interpreter runs
the code you attached to them in that description, so far so good.
A virtual property or method allows you to run some code in the property
or method implementation, which usually just records some data in the
object's storage, and then return the object itself via RETURN_SELF
(GB_PROPERTY_SELF is a shorthand for just returning self and not doing
anything else) *but* the interpreter treats the return value (still the
same object) not as being of its true type but of the return type that
is given in the property declaration.
Suddenly, the same object has a completely different interface, new methods,
new properties. But it's the same region in memory, so the implementations
of these new properties and methods can access the original object. This is
normally used to provide a specialized view on the object.
All this implies, by the way, that you cannot store virtual objects in memory,
because they are just temporary views on another object. And that using
virtual object is inherently thread-unsafe because, depending on respective
implementation, there may only be one virtual object for a given real object
at any time in the process.
> I am trying to keep everything in Gambas itself.
You can't implement virtual classes in Gambas. You can only do that using
the native C/C++ API of the interpreter, which has the magic of switching
one interface description blob for another. Everything you write in Gambas
is a real class where you can't detach storage from interface.
Virtual classes are really just a hack in the interpreter to "parametrically
cast" an object to another class for the sake of not polluting the, say,
Array class's direct interface with methods and properties related to its
bounds, as those can be hidden in a virtual view on the array. Virtual classes
allow to do this: (1) cheaply (because all that needs to be done is replace
the pointer to the type of an object) and (2) without having to create new
objects and hence making interfaces of the original class (semi-)public so
that those new objects can access them.
The usual way to emulate this in Gambas is to:
- make real classes for the virtual views, like _Array_Bounds with
a constructor of _new(RealObject As Array),
- Array.Bounds returns a new instance of this _Array_Bounds and
passes the Me reference to the constructor,
- the Array class needs to make certain internals public so that
_Array_Bounds can access them, being a different object now.
Customarily these are prefixed by an underscore so that the IDE
hides them from normal people's views.
You'd be surprised how far into the internals of Gambas-written components
like gb.gui.base you can go, because they all do the above, with slight
variations. See for example the GridView and associated classes .
"There's an old saying: Don't change anything... ever!" -- Mr. Monk
----[ http://gambaswiki.org/wiki/doc/netiquette ]----
More information about the User