Modifying things with Automatic inheritance (Quick HowTo)
Posted
#1
(In Topic #890)
Guru

This is massively useful for simply adding properties to existing gambas classes or to override some of a built in classes functions.
Also massively useful for backward compatibly as you can auto add or override things (read on for more info)
Note: an "override" as discussed here is only relevant to built in gambas classes or component classes that you otherwise do not have in your own program.
How you do it…
Lets show you a simple example…
Say you want the Timers in your application to also have a .Tag property.
So in your application make a new class and name it Timer.class
Add the following code to it…
That's it. Now you will find all your Timer objects also have a Tag property.
Automatic inheritance will automatically make your Timer.class inherit the existing Timer.class as it has the same name.
As Timer can be a virtual IDE object i also added Tag to the _Properties string constant making it visible in the IDE form designer.
[hr]
You can go much further than adding new properties/methods to existing classes, you can also override class methods by making your own versions.
Take this example where I want the Timer to have a Stopped event raised if the timer gets disabled. (again the class is just called Timer.class)
Code (gambas)
- ' Gambas class file
- Event Stopped
- ' Set the inherited Timer.class Enabled property.
- ' Raise the Stopped event if not enabled
In that example we are overriding the Enabled property and the Stop() method.
Setting Timer.Enabled is now handled by our class, it sets the inherited Timer.Enabled property using Super.Enabled and raises the Stopped event if set to false.
The Stop() method is also overridden to set our own Enabled property and trigger the Stopped event.
[hr]
This can also be very useful for backward compatibility.
I had a problem with one of my applications once where i had used the Collection.Keys property not realizing that Keys is new to gambas 3.17. so anyone using an older gambas got an error.
The solution…
I create a class in my application called Collection.class
add the following code..
Now I am using my own Keys property with Collection.
If an older gambas the Keys property will be added to Collection, if a new gambas then it will be overridden.
[hr]
Note:
Properties and methods you override in a class will block the inherited classes properties/methods.
Use the Super keyword to access the inherited class things.
As i have in the second example where i set Super.Enabled, this sets the Enabled property of the inherited Timer.class not my one.
Happy coding.
Bruce
Posted
Guru

you could make one of the above examples work more accurately to not just override but use either your added property/method if the users gambas is older and does not have it or using an existing thing if it exists using Try and Error.
eg. (File named Collection.class)
Code (gambas)
- ' Gambas class file
- Return sKeys
So in that example we Try to get the Keys property from Super (the inherited Collection.class)
If gambas is 3.17+ then it will use the existing Collection.Keys property.
If an older gambas it will see the error and do it itself.
Similar methods can be used in many cases to either use a classes existing property/method or use your own if the gambas version is missing it.
Posted
Regular

Your thoughts on this however are probably worth a help howto! You've got the time haven't you
Now, just to get serious (and don't call me Shirley!) one thing I am currently having a minor problem is this and your thoughts are welcome. I have used this approach in the past and sometimes I get caught up in a total mind block when I don't realize that I am using a local class override and can't understand why the class does not behave as I expect from the native class. Obscure, yes, but… it would be "nice" to know somehow whether the current instance of an object is the native version, an override in the current project or more importantly an override introduced in some intervening library or component… there are security implications…
Any thoughts?
b (t'other b)
Posted
Guru

thatbruce said
Very good. But one observation (of course :twisted: ), AFAIK you cannot override event handlers. If for example you try to override the (self)_Timer event handler then both yours and the native timer events will be called and (AFAIK) there is no way to determine which is called first. Just a caveat.
Your thoughts on this however are probably worth a help howto! You've got the time haven't you![]()
Now, just to get serious (and don't call me Shirley!) one thing I am currently having a minor problem is this and your thoughts are welcome. I have used this approach in the past and sometimes I get caught up in a total mind block when I don't realize that I am using a local class override and can't understand why the class does not behave as I expect from the native class. Obscure, yes, but… it would be "nice" to know somehow whether the current instance of an object is the native version, an override in the current project or more importantly an override introduced in some intervening library or component… there are security implications…
Any thoughts?
b (t'other b)
Hmm, i though you could override events just fine.
like this (file named Button.class)
that works okay, the button will not fire a Click event as overidden to fire the Myclick event.
I'm not sure i get the issue but my experience is to say try to override as little of the class as possible (just the methods you need)
I've had some troubles where i cannot access the class data needed to override properly. and trying to copy a whole class into a project as an override often get issues not being able to find various attached objects, sometimes importing the whole component is the way to go there.
But sure Events can be overridden with Stop Event and methods/ properties can all be overridden.
Security wise i'm not sure i understand?
maybe you could do some sneaky stuff somehow or other but i guess you could do that without inheritance , the openness of your source will be your undoing
There probably is a way to see if a class has overrides (Ben would be the guy to ask about the easiest way to do that)
maybe by checking out the object/class hierarchy ?
Respects
English Bruce
Posted
Guru

thatbruce said
Very good. But one observation (of course :twisted: ), AFAIK you cannot override event handlers. If for example you try to override the (self)_Timer event handler then both yours and the native timer events will be called and (AFAIK) there is no way to determine which is called first. Just a caveat.
okay i had a play and it seems the Timer_Timer() event is a good example there of what not to override. you cannot so much "override" the timer event because if you stop the event the inherited timer misses it's trigger and does not trigger again? odd
But you CAN intercept the Timer_Timer() event and do stuff in it like raise other events, set properties, etc but gotta let it trigger it's internal event
If you use that Timer.class and use both the Timer and MyTimer event handlers then you find the intercept MyTimer triggers before Timer
produces this…
Code
trigger event No 1
timer event
trigger event No 2
timer event
trigger event No 3
timer eventRespects.
Posted
Enthusiast

Code (gambas)
Posted
Guru

Posted
Guru

Seems like a bug
If you rename the class to TextLabel2.class and add "Inherits TextLabel" then it all works as expected.
Posted
Enthusiast

BruceSteers said
I tried your code and got the variables in the IDE but could not change them.
same here …
I know … but thats nt what I wantBruceSteers said
If you rename the class to TextLabel2.class and add "Inherits TextLabel" then it all works as expected.
BruceSteers said
Seems like a bug
Posted
Guru

PJBlack said
BruceSteers said
I tried your code and got the variables in the IDE but could not change them.
same here …
I know … but thats nt what I wantBruceSteers said
If you rename the class to TextLabel2.class and add "Inherits TextLabel" then it all works as expected.
BruceSteers said
Seems like a bug
![]()
then fix it
Haha
I have asked the experts for a reason as to why it does not work……..
Posted
Enthusiast

BruceSteers said
[I have asked the experts for a reason as to why it does not work……..
have read …
the property did not show up in the .form because false is the default value for it … having a textlabel2.class then the property show up in .form only if changed to true
Posted
Guru

I just checked.
Yep , it's fixed
Posted
Regular

Posted
Regular

I have created a class file named Collection which contains an additional public function (method) named 'Exists'…
(I tried to override the class method 'Exist', but got an error "incorrectly overridden" at runtime, so went for Exists function instead)!??
A simple test of the method, with a key:value added to my declared Collection data-type, worked fine,
but at runtime another bit of code (which normally works ok) that reads a json file into a Collection variable failed with the attached error
Am I missing a bit more code/or a setting in my Collections class file?
Thanks,
C
Posted
Guru

hard to tell what your problem is without seeing more code,
seems it does not like ^Collection which i think means Pointer to Collection
Note: you ARE using ByRef on both sides of the call yes?
Ie.
Posted
Regular

Was using byRef correctly - both sides - but this error is raised even when my Exists method calls are commented-out, ie. unused!
The line of code highlighted blue, works fine if I take out my overriding Collection class file. So if you're correct, something about using an overridden data-type class: Collection is causing a data-type confusion where a variable 'as Collection' is declared, OR, the internal output of my JSON.Decode statement is ending up as a pointer rather than a Collection???
I don't know enough about using pointers to get my code back on track :?
Anything you can see that might be added/altered or tried instead?
Ta,
C
Posted
Guru

I have no problem overriding Collection.class here , i just ried your Exists method and no problems.
make a sample program and post it, then we can see all that might be causing the error.
or post the file it is loading (filespec)
i suspect a json decode error
Posted
Regular

The overridden class is still loaded and replaces the native reference one in the symbol table even if your inserted method is not used.chrisRoald said
but this error is raised even when my Exists method calls are commented-out, ie. unused!
Suggest, check the typeof the return value from the JSON.Decode. It should be a variant, which I think in this case means it is a pointer. It looks like the Collection class bit that converts a variant to a real collection is failing.
Maybe use a JSONCollection instead? (not tried).
b
Posted
Guru

like this…
But i found a fix to convert the ^Collection to Collection by simply using Copy() on the result,
try this…
Posted
Guru

Like for example Collection.class is not just used in your application , many of the loaded components use Collection too,
you can break things by changing the way built in classes original methods work. that's probably why you have to match the arguments and types.
It would be better in your case I think to add an Exists() method rather than modify the existing Collection.Exist() as that could cause unforseen problems.
Good luck
Posted
Guru

by saving this as JSON.module
hehe
Posted
Regular

.Copy was the one idea I didn't get to :roll: Thanks for that.
I'll bear in mind the future possible conflicts issue with overriding. I have however learnt how to create my own datatype - class - as I renamed Collection to Collectionb and used Inherits which could prove more useful/flexible in future.
Thanks again,
C.
Posted
Regular

BruceSteers said
Is hVar freed when it goes out of scope at line 7?
b
Posted
Regular

A long time for me with no post.
I try to override a class in my project and it's seam to be not possible.
For exemple in my project i've
FMain
Class1
I whant to override Class1 but I can't create a new class1 because IDE said me that the name already exist.
What do you thinq about this ????
Regards
Olivier
Posted
Guru

If the Class1.class is in your project then you have the Class1.class , it does not need to be overridden?, you can just change it.
So i think it does not make sense what you are trying to do.
Maybe you are looking to Inherit ?
You could make a Class2.class and make it Inherit Class1.class then it would be the same as Class1 but with your modifications.
1 guest and 0 members have just viewed this.




